;  DK200A.ASM 2002.07.31 @ 20:00 CST
;  See RFM Virtual Wire(r) Development Kit Warranty & License for terms of use
;  Experimental software - NO representation is
;  made that this software is suitable for any purpose
;  Copyright(c) 2000 - 2002, RF Monolithics, Inc.
;  AT89C2051 assembler source code file (TASM 3.01 assembler)
;  Low signal-to-noise protocol for RFM ASH transceiver
;  Integrate & dump PLL (I&D) - 62.40 us tick

          .NOLIST
          #INCLUDE "8051.H"        ;  tasm 8051 include file
          .LIST

;  constants:

ITMOD     .EQU      022H           ;  set timers 0 and 1 to mode 2
ITICK     .EQU      141            ;  set timer T0 for 62.40 us tick
ISMOD     .EQU      080H           ;  SMOD = 1 in PCON
IBAUD     .EQU      0FAH           ;  19.2 kbps @ 22.1184 MHz, SMOD = 1
ISCON     .EQU      050H           ;  UART mode 1

RMPT      .EQU      159            ;  PLL ramp top value (modulo 0 to 159)
RMPW      .EQU      159            ;  PLL ramp reset (wrap) value
RMPS      .EQU      80             ;  PLL ramp switch value
RMPI      .EQU      20             ;  PLL ramp increment value
RMPA      .EQU      29             ;  PLL 5.625% advance increment value (20 + 9)
RMPR      .EQU      11             ;  PLL 5.625% retard increment value (20 - 9)

AKMB      .EQU      03EH           ;  ACK message buffer start address
TXMB      .EQU      043H           ;  TX message buffer start address
TFTX      .EQU      044H           ;  TO/FROM TX message buffer address
IDTX      .EQU      045H           ;  packet ID TX message buffer address
RXMB      .EQU      061H           ;  RX message buffer start address
TFRX      .EQU      062H           ;  TO/FROM RX message buffer address
IDRX      .EQU      063H           ;  packet ID RX message buffer address
FEND      .EQU      0C0H           ;  FEND framing character (192)
SOPL      .EQU      08AH           ;  SOP low correlator pattern
SOPH      .EQU      0B3H           ;  SOP high correlator pattern
TXR0      .EQU      026H           ;  TX retry timer count

FCSS      .EQU      0FFH           ;  FCS seed
FCSH      .EQU      084H           ;  FCS high XOR mask
FCSL      .EQU      08H            ;  FCS low XOR mask
FCVH      .EQU      0F0H           ;  FCS valid high byte pattern
FCVL      .EQU      0B8H           ;  FCS valid low byte pattern

;  stack:  08H - 021H (26 bytes)

;  bit labels:

WBFLG     .EQU      010H           ;  warm boot flag (future use)
PLLON     .EQU      011H           ;  RX PLL control flag
RXISM     .EQU      012H           ;  RX inverted input sample
RXSMP     .EQU      013H           ;  RX input sample
LRXSM     .EQU      014H           ;  last RX input sample
RXBIT     .EQU      015H           ;  RX input bit
RXBFLG    .EQU      016H           ;  RX input bit flag
SOPFLG    .EQU      017H           ;  SOP detect flag
RXSFLG    .EQU      018H           ;  RX symbol flag
RM        .EQU      019H           ;  RX FCS message bit
OKFLG     .EQU      01AH           ;  RX FCS OK flag

SIFLG     .EQU      01BH           ;  serial in active flag
TSFLG     .EQU      01CH           ;  output TX sample flag
TXBIT     .EQU      01DH           ;  TX message bit
TM        .EQU      01EH           ;  TX FCS message bit
TXFLG     .EQU      01FH           ;  TX active flag
TMFLG     .EQU      020H           ;  TX message flag
TOFLG     .EQU      021H           ;  get message time out flag

AMFLG     .EQU      022H           ;  AutoSend message flag
ASFLG     .EQU      023H           ;  AutoSend active flag
ANFLG     .EQU      024H           ;  ACK/NAK status flag
SAFLG     .EQU      025H           ;  send ACK/NAK flag
NHFLG     .EQU      026H           ;  no RX FEND/header flag

SFLG1     .EQU      027H           ;  spare flag 1
SFLG2     .EQU      028H           ;  spare flag 2
SFLG3     .EQU      029H           ;  spare flag 3
SFLG4     .EQU      02AH           ;  spare flag 4
SFLG5     .EQU      02BH           ;  spare flag 5
SFLG6     .EQU      02CH           ;  spare flag 6
SFLG7     .EQU      02DH           ;  spare flag 7
SFLG8     .EQU      02EH           ;  spare flag 8
SFLG9     .EQU      02FH           ;  spare flag 9

;  register usage:

;  R0                                 RX data pointer
;  R1                                 TX data pointer
;  R2                                 PLL ramp buffer
;  R3                                 RX FCS buffer A
;  R4                                 not used
;  R5                                 TX FCS buffer A
;  R6                                 TX FCS buffer B
;  R7                                 RX FCS buffer B

;  byte labels:

BOOT      .EQU      022H           ;  1st byte of flags

RXID      .EQU      026H           ;  RX integrate & dump buffer
RXBL      .EQU      027H           ;  RX low buffer, SOP correlator, etc.
RXBH      .EQU      028H           ;  RX high buffer, SOP correlator, etc.
RXBB      .EQU      029H           ;  RX symbol decode byte buffer
RMDC      .EQU      02AH           ;  RX symbol decode loop counter
RMBIC     .EQU      02BH           ;  RX symbol decode index pointer
RMBYC     .EQU      02CH           ;  RX message byte counter
RMFCS     .EQU      02DH           ;  RX FCS byte buffer
RMSBC     .EQU      02EH           ;  RX symbol bit counter
RMLPC     .EQU      02FH           ;  RX message loop counter
RMFCC     .EQU      030H           ;  RX message FCS counter, etc.

TMFCC     .EQU      031H           ;  TX timer & loop counter
TXSMC     .EQU      032H           ;  TX output sample counter
TMBIC     .EQU      033H           ;  TX message bit counter
TMBYT     .EQU      034H           ;  TX message byte buffer
TMBYC     .EQU      035H           ;  TX message byte counter
TXSL      .EQU      036H           ;  TX message symbol low buffer
TXSH      .EQU      037H           ;  TX message symbol high buffer
TMFCS     .EQU      038H           ;  TX FCS byte buffer
TXTL      .EQU      039H           ;  TX timer low byte
TXTH      .EQU      03AH           ;  TX timer high byte
TXCNT     .EQU      03BH           ;  TX retry counter
IDBUF     .EQU      03CH           ;  packet ID buffer
TFBUF     .EQU      03DH           ;  TO/FROM address buffer

;  I/O pins:

MAX       .EQU      P1.6           ;  Maxim 218 power (on = 1)

RXPIN     .EQU      P3.2           ;  RX input pin (inverted data)
TXPIN     .EQU      P3.3           ;  TX output pin (on = 1)
PTT       .EQU      P1.7           ;  transmit enable (TX = 0)

PCRCV     .EQU      P3.7           ;  PC (host) input LED (on = 0)
RFRCV     .EQU      P3.5           ;  RX FCS OK LED (on = 0)
RXI       .EQU      P3.4           ;  RX activity LED (on = 0)

ID0       .EQU      P1.2           ;  jumper input bit 0 (dot end)
ID1       .EQU      P1.3           ;  jumper input bit 1
ID2       .EQU      P1.4           ;  jumper input bit 2
ID3       .EQU      P1.5           ;  jumper input bit 3

;  start of code:

          .ORG      00H            ;  hardware reset
          SETB      WBFLG          ;  set warm boot flag
reset:    AJMP      start          ;  jump to start

          .ORG      0BH            ;  timer 0 interrupt vector
t_isr:    ACALL     tick           ;  sampling tick subroutine
          RETI                     ;  interrupt done

          .ORG      023H           ;  serial interrupt vector
s_isr:    ACALL     srio           ;  serial I/O subroutine
          CLR       TI             ;  clear TI (byte sent) flag
          CLR       RI             ;  clear RI (byte received) flag
          RETI                     ;  interrupt done

          .ORG      040H           ;  above interrupt code space
start:    ACALL     setup          ;  initialization code

main:     JNB       AMFLG,mn0      ;  skip if AutoSend idle
          CLR       PCRCV          ;  else turn PCRCV LED on
          ACALL     do_as          ;  do AutoSend
          SETB      PCRCV          ;  turn PCRCV LED off
          AJMP      mn1            ;  and jump to RX SOP detect 
mn0:      JNB       TMFLG,mn1      ;  skip if TX message idle
          CLR       PCRCV          ;  else turn PCRCV LED on
          ACALL     do_rt          ;  do TX retry
          SETB      PCRCV          ;  turn PCRCV LED off
mn1:      JNB       SAFLG,mn2      ;  skip if send ACK/NAK flag reset
          ACALL     aksnd          ;  else send NAK to host
mn2:      ACALL     rxsop          ;  do RX SOP detect
          JNB       SOPFLG,main    ;  if not SOP loop to main
          ACALL     do_rx          ;  else do RX message
mn_d:     AJMP      main           ;  and loop to main

do_rx:    CLR       ES             ;  deactivate serial interrupts
          ACALL     rxmsg          ;  decode RX message
          CLR       PLLON          ;  idle RX PLL
          ACALL     rxfcs          ;  test RX message FCS
          JNB       OKFLG,rx2      ;  reset if FCS error
          JNB       TXFLG,rx0      ;  skip if send TX idle
          ACALL     acktx          ;  if TX ACK, set send ACK flag
          JNB       SAFLG,rx0      ;  skip if send ACK/NAK flag reset
          ACALL     aksnd          ;  else send ACK message to host
          AJMP      rx2            ;  and jump to reset RX
rx0:      JB        ASFLG,rx1      ;  don't ACK AutoSend
          ACALL     ackrx          ;  ACK RX message
rx1:      ACALL     rxsnd          ;  send RX message to host
rx2:      ACALL     rxrst          ;  reset for next RX message
          SETB      PLLON          ;  enable RX PLL
          CLR       TI             ;  clear TI flag
          CLR       RI             ;  clear RI flag
          SETB      ES             ;  activate serial interrupts
rx_d:     RET                      ;  RX done

tick:     PUSH      PSW            ;  push status
          PUSH      ACC            ;  push accumulator
          MOV       C,RXPIN        ;  read RX input pin
          MOV       RXISM,C        ;  store as inverted RX sample
          JNB       TSFLG,tic0     ;  skip if TX sample out idle
          MOV       A,TXSMC        ;  else get sample count
          JZ        tic0           ;  skip if 0
          MOV       C,TXBIT        ;  else load TX bit
          MOV       TXPIN,C        ;  into TX output pin
          DEC       TXSMC          ;  decrement sample count
tic0:     JNB       PLLON,tic1     ;  skip if PLL idle
          ACALL     pll            ;  else run RX PLL
tic1:     JNB       TOFLG,tic2     ;  skip if get message timeout idle
          INC       TMFCC          ;  else bump timeout counter
          MOV       A,TMFCC        ;  get counter
          CJNE      A,#50,tic2     ;  skip if counter <> 50 (5.2 ms)
          CLR       TOFLG          ;  else reset time out flag
          MOV       TMFCC,#0       ;  reset counter
tic2:     INC       TXTL           ;  bump TX timer low
          MOV       A,TXTL         ;  load TX timer low
          JNZ       tick_d         ;  done if no rollover
          JNB       ASFLG,tic3     ;  skip if AutoSend idle
          DJNZ      TXTH,tick_d    ;  decrement TXTH, done if <> 0
          SETB      AMFLG          ;  else set AM message flag
          MOV       TXTL,#0        ;  clear TX delay low
          MOV       TXTH,#TXR0     ;  reload TX delay high
          AJMP      tick_d         ;  and jump to tic6
tic3:     JNB       TXFLG,tick_d   ;  skip if TX idle
          DJNZ      TXTH,tick_d    ;  decrement TXTH, done if <> 0
          SETB      TMFLG          ;  else set TM message flag
          MOV       DPTR,#delay    ;  point to delay table
          MOV       A,TL1          ;  get random table offset 
          ANL       A,#07H         ;  mask out upper 5 bits
          MOVC      A,@A+DPTR      ;  load byte from table
          MOV       TXTH,A         ;  into TX delay high
          MOV       TXTL,#0        ;  clear TX delay low
          MOV       A,TXCNT        ;  load retry count
          CJNE      A,#9,tick_d    ;  if <> 9 jump to tick_d
          CLR       TMFLG          ;  else reset send TX message
          CLR       ANFLG          ;  reset ACK/NAK flag (NAK)
          SETB      SAFLG          ;  set send ACK/NAK flag
          CLR       TXFLG          ;  reset TX active flag
tick_d:   POP       ACC            ;  pop accumulator
          POP       PSW            ;  pop status
          RET                      ;  tick done

pll:      MOV       C,RXSMP        ;  load RX sample
          MOV       LRXSM,C        ;  into last RX sample
          MOV       C,RXISM        ;  get inverted RX sample
          CPL       C              ;  invert sample
          MOV       RXSMP,C        ;  and store RX sample
          JNC       pll0           ;  if <> 1 jump to pll0
          INC       RXID           ;  else increment I&D
pll0:     JNB       LRXSM,pll1     ;  if last sample 1
          CPL       C              ;  invert current sample
pll1:     JNC       pll4           ;  if no edge jump to pll4
          MOV       A,R2           ;  else get PLL value
          CLR       C              ;  clear borrow
          SUBB      A,#RMPS        ;  subtract ramp switch value
          JC        pll3           ;  if < 0 then retard PLL
pll2:     MOV       A,R2           ;  else get PLL value
          ADD       A,#RMPA        ;  add (RMPI + 5.625%)
          MOV       R2,A           ;  store PLL value
          AJMP      pll5           ;  and jump to pll5
pll3:     MOV       A,R2           ;  get PLL value
          ADD       A,#RMPR        ;  add (RMPI - 5.625%)
          MOV       R2,A           ;  store PLL value
          AJMP      pll5           ;  and jump to pll5
pll4:     MOV       A,R2           ;  get PLL value
          ADD       A,#RMPI        ;  add ramp increment
          MOV       R2,A           ;  store new PLL value
pll5:     CLR       C              ;  clear borrow
          MOV       A,R2           ;  get PLL ramp value
          SUBB      A,#RMPT        ;  subtract ramp top
          JC        pllD           ;  if < 0 don't wrap
pll6:     MOV       A,R2           ;  else get PLL value
          CLR       C              ;  clear borrow
          SUBB      A,#RMPW        ;  subtract reset value
          MOV       R2,A           ;  and store result
          CLR       C              ;  clear borrow
          MOV       A,RXID         ;  get I&D buffer
          SUBB      A,#5           ;  subtract 5
          JNC       pll7           ;  if I&D count => 5 jump to pll7
          CLR       RXBIT          ;  else RX bit = 0 for I&D count < 5
          SETB      RXBFLG         ;  set new RX bit flag
          MOV       RXID,#0        ;  clear the I&D buffer
          AJMP      pll8           ;  and jump to pll8
pll7:     SETB      RXBIT          ;  RX bit = 1 for I&D count => 5
          SETB      RXBFLG         ;  set new RX bit flag
          MOV       RXID,#0        ;  clear the I&D buffer
pll8:     JB        SOPFLG,pllA    ;  skip after SOP detect
          MOV       A,RXBH         ;  else get RXBH
          CLR       C              ;  clear carry
          RRC       A              ;  rotate right
          JNB       RXBIT,pll9     ;  if bit = 0 jump to pll9
          SETB      ACC.7          ;  else set 7th bit
pll9:     MOV       RXBH,A         ;  store RXBH
          MOV       A,RXBL         ;  get RXBL
          RRC       A              ;  shift and pull in carry
          MOV       RXBL,A         ;  store RXBL
          AJMP      pll_d          ;  done for now
pllA:     MOV       A,RXBL         ;  get RXBL
          CLR       C              ;  clear carry
          RRC       A              ;  shift right
          JNB       RXBIT,pllB     ;  if bit = 0 jump to pllB
          SETB      ACC.5          ;  else set 5th bit
pllB:     MOV       RXBL,A         ;  store RXBL
          INC       RMSBC          ;  bump bit counter
          MOV       A,RMSBC        ;  get counter 
          CJNE      A,#6,pllC      ;  if <> 6 jump to pllC
          MOV       RXBB,RXBL      ;  else get symbol
          MOV       RMSBC,#0       ;  reset counter
          SETB      RXSFLG         ;  set symbol flag
pllC:     AJMP      pll_d          ;  done for now
pllD:     CLR       RXBFLG         ;  clear RXBFLG
pll_d:    RET                      ;  PLL done

rxsop:    JNB       RXBFLG,sop_d   ;  done if no RX bit flag
          CLR       RXBFLG         ;  else clear RX bit flag
          MOV       A,RXBL         ;  get low RX buffer
          CJNE      A,#SOPL,sop_d  ;  done if <> SOPL
          MOV       A,RXBH         ;  else get high RX buffer
          CJNE      A,#SOPH,sop_d  ;  done if <> SOPH
          CLR       A              ;  else clear A
          MOV       RXBL,A         ;  clear RX low buffer
          MOV       RXBH,A         ;  clear RX high buffer
          MOV       RMSBC,A        ;  clear RX symbol bit counter
          CLR       RXSFLG         ;  clear RX symbol flag
          SETB      SOPFLG         ;  set SOP detected flag
          CLR       RXI            ;  RXI LED on
sop_d:    RET                      ;  SOP detect done

rxmsg:    JNB       RXSFLG,rxmsg   ;  wait for RX symbol flag
          CLR       RXSFLG         ;  clear RX symbol flag
rxm1:     MOV       DPTR,#smbl     ;  point to RX symbol decode table
          MOV       RMDC,#16       ;  16 symbol decode table entries
          MOV       RMBIC,#0       ;  index into symbol table
rxm2:     MOV       A,RMBIC        ;  load index into A
          MOVC      A,@A+DPTR      ;  get table entry
          XRL       A,RXBB         ;  XOR to compare with RXBB
          JZ        rxm3           ;  exit loop with decoded nibble
          INC       RMBIC          ;  else bump index
          DJNZ      RMDC,rxm2      ;  and try to decode again
rxm3:     MOV       A,RMBIC        ;  get decoded nibble
          SWAP      A              ;  swap to high nibble
          MOV       RXBH,A         ;  into RXBH (low nibble is high)
rxm4:     JNB       RXSFLG,rxm4    ;  wait for symbol flag
          CLR       RXSFLG         ;  clear flag
rxm5:     MOV       DPTR,#smbl     ;  point to symbol decode table
          MOV       RMDC,#16       ;  16 symbol decode table entries
          MOV       RMBIC,#0       ;  reset symbol table index
rxm6:     MOV       A,RMBIC        ;  load index into A
          MOVC      A,@A+DPTR      ;  get table entry
          XRL       A,RXBB         ;  XOR to compare with RXBB
          JZ        rxm7           ;  exit loop with decoded nibble
          INC       RMBIC          ;  else bump index
          DJNZ      RMDC,rxm6      ;  and try to decode again
rxm7:     MOV       A,RMBIC        ;  get decoded nibble
          ORL       A,RXBH         ;  add RXBH low
          SWAP      A              ;  nibbles now in right order
          MOV       RXBH,A         ;  store in RXBH
          MOV       @R0,RXBH       ;  and store in RX message buffer
          CJNE      R0,#RXMB,rxm8  ;  skip if not 1st message byte
          MOV       A,RXBH         ;  else get 1st byte
          ANL       A,#63          ;  mask upper 2 bits
          MOV       RMBYC,A        ;  load message byte counter
          MOV       RMFCC,A        ;  and RX message loop counter
          CLR       C              ;  clear borrow
          SUBB      A,#30          ;  compare number of bytes to 30
          JC        rxm8           ;  skip if < 30
          MOV       RMBYC,#4       ;  else force byte counter to 4
          MOV       RMFCC,#4       ;  and force loop counter to 4
rxm8:     INC       R0             ;  bump pointer
          DJNZ      RMFCC,rxmsg    ;  if <> 0 get another byte
          MOV       R0,#RXMB       ;  reset RX message pointer
          SETB      RXI            ;  turn LED off
rxm_d:    RET                      ;  RX message done

rxfcs:    MOV       RMFCC,RMBYC    ;  move byte count to loop counter
rxf0:     MOV       RMFCS,@R0      ;  get next message byte
          INC       R0             ;  bump pointer
          ACALL     b_rfcs         ;  build FCS
          DJNZ      RMFCC,rxf0     ;  loop for next byte
          ACALL     a_rfcs         ;  test FCS
rxf_d:    RET                      ;  RX FCS done

acktx:    MOV      A,RXMB          ;  get 1st RX byte
          ANL      A,#64           ;  mask ACK bit
          CJNE     A,#64,atx_d     ;  done if <> ACK
          MOV      A,TFBUF         ;  else get TX TO/FROM
          SWAP     A               ;  swap for FROM/TO
          CJNE     A,TFRX,atx_d    ;  done if <> RX TO/FROM
          MOV      A,IDBUF         ;  else get TX packet ID
          CJNE     A,IDRX,atx_d    ;  done if <> TX ID
          SETB     ANFLG           ;  else set ACK/NAK flag (ACK)
          SETB     SAFLG           ;  set send ACK/NAK message flag
          CLR      TXFLG           ;  clear TX active flag
atx_d:    RET                      ;  ACK TX done

ackrx:    MOV       A,TFBUF        ;  get local TO/FROM address
          ANL       A,#15          ;  mask to get local FROM address
          MOV       B,A            ;  store FROM address
          MOV       A,TFRX         ;  get T/F address from RX buffer
          SWAP      A              ;  swap - FROM/TO
          ANL       A,#15          ;  mask to get TO address
          CJNE      A,B,arx0       ;  done if not to this node
          MOV       R1,#AKMB       ;  load ACK pointer
          MOV       @R1,#69        ;  ACK bit + 5 bytes
          MOV       TMFCS,#69      ;  load TX message FCS byte
          ACALL     b_tfcs         ;  and build FCS
          INC       R1             ;  bump pointer
          MOV       A,TFRX         ;  get TO/FROM byte
          SWAP      A              ;  swap TO/FROM addresses
          MOV       @R1,A          ;  add to ACK buffer
          MOV       TMFCS,A        ;  load TX message FCS byte
          ACALL     b_tfcs         ;  and build FCS
          INC       R1             ;  bump pointer
          MOV       A,IDRX         ;  get packet ID byte
          MOV       @R1,A          ;  add ID to ACK message
          MOV       TMFCS,A        ;  load TX message FCS byte
          ACALL     b_tfcs         ;  and build FCS
          INC       R1             ;  bump pointer
          ACALL     a_tfcs         ;  add FCS
          MOV       R1,#AKMB       ;  reset ACK pointer
          PUSH      TMBYC          ;  push TX message TMBYC
          MOV       TMBYC,#5       ;  5 bytes in ACK
          ACALL     txpre          ;  send TX preamble
          ACALL     txmsg          ;  send TX message
          CLR       A              ;  reset for next TX
          MOV       TMBYT,A        ;  clear TX message byte
          MOV       TXSMC,A        ;  clear TX out count
          MOV       TXSL,A         ;  clear TX symbol low
          MOV       TXSH,A         ;  clear TX symbol high
          MOV       R1,#TXMB       ;  point R1 to message start
          POP       TMBYC          ;  restore TX message TMBYC
arx0:     SETB      RFRCV          ;  turn FCS LED off
arx_d:    RET                      ;  RX ACK done (rxsnd sets ES)

rxsnd:    CLR       PCRCV          ;  turn PC LED on
          MOV       A,TFBUF        ;  get local TO/FROM address
          ANL       A,#15          ;  mask to get local FROM address
          MOV       B,A            ;  store FROM address
          MOV       A,TFRX         ;  get T/F address from RX buffer
          SWAP      A              ;  swap - FROM/TO
          ANL       A,#15          ;  mask to get TO address
          CJNE      A,B,rxs4       ;  if <> don't send to host
          DEC       RMBYC          ;  don't send
          DEC       RMBYC          ;  the 2 FCS bytes
          MOV       R0,#RXMB       ;  reset RX message pointer
          MOV       @R0,#FEND      ;  replace # bytes with 1st FEND
          JNB       NHFLG,rxs0     ;  skip if no FEND/header flag reset
          INC       R0             ;  bump past FEND
          DEC       RMBYC          ;  decrement byte count
          INC       R0             ;  bump past TO/FROM
          DEC       RMBYC          ;  decrement byte count
          INC       R0             ;  bump past ID
          DEC       RMBYC          ;  decrement byte count
rxs0:     CLR       TI             ;  clear TI flag
rxs1:     MOV       SBUF,@R0       ;  send byte
rxs2:     JNB       TI,rxs2        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          INC       R0             ;  bump pointer
          DJNZ      RMBYC,rxs1     ;  loop to echo message
          JB        NHFLG,rxs4     ;  skip if no FEND/header flag set
          MOV       SBUF,#FEND     ;  add 2nd FEND
rxs3:     JNB       TI,rxs3        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
rxs4:     SETB      RFRCV          ;  turn FCS LED off
          SETB      PCRCV          ;  turn PC LED off
rxs_d:    RET                      ;  send RX message done

aksnd:    CLR       ES             ;  disable serial interrupts
          CLR       PCRCV          ;  turn PC LED on
          CLR       SAFLG          ;  reset send ACK/NAK flag
          CLR       TXFLG          ;  reset TX active flag
          MOV       A,IDBUF        ;  get local ID
          ANL       A,#7           ;  mask unused bits
          SWAP      A              ;  swap ID to upper IDS nibble
          ADD       A,TXCNT        ;  add retry count to IDS
          JNB       ANFLG,aks0     ;  skip if NAK
          ADD       A,#128         ;  else set ACK bit
aks0:     MOV       B,A            ;  hold IDS in B
          MOV       A,TFBUF        ;  get local TO/FROM
          SWAP      A              ;  switch TO and FROM
          CLR       TI             ;  clear TI flag
          MOV       SBUF,#FEND     ;  send 1st FEND
aks1:     JNB       TI,aks1        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          MOV       SBUF,A         ;  send TO/FROM
aks2:     JNB       TI,aks2        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          MOV       SBUF,B         ;  send IDS
aks3:     JNB       TI,aks3        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          MOV       SBUF,#FEND     ;  send 2nd FEND
aks4:     JNB       TI,aks4        ;  wait until byte sent
          ACALL     txrst          ;  reset TX state
          SETB      RFRCV          ;  turn FCS LED off
          SETB      PCRCV          ;  turn PC LED off
          CLR       TI             ;  clear TI flag
          CLR       RI             ;  clear RI flag
          SETB      ES             ;  enable serial interrupts
aks_d:    RET                      ;  send ACK message done

rxrst:    CLR       A              ;  clear A
          MOV       RXBH,A         ;  clear buffer
          MOV       RXBL,A         ;  clear buffer
          MOV       RXBB,A         ;  clear buffer
          MOV       RMBYC,A        ;  clear RX byte count
          MOV       RMFCC,A        ;  clear loop counter
          MOV       R0,#RXMB       ;  point R0 to message start
          CLR       OKFLG          ;  clear FCS OK flag
          CLR       SOPFLG         ;  enable SOP test
          SETB      RXI            ;  turn RXI LED off
rxr_d:    RET                      ;  RX reset done

b_rfcs:   MOV       RMLPC,#8       ;  load loop count of 8
brf0:     CLR       C              ;  clear carry bit
          MOV       A,RMFCS        ;  load RX message byte
          RRC       A              ;  shift lsb into carry
          MOV       RMFCS,A        ;  store shifted message byte
          MOV       RM,C           ;  load RM with lsb
          CLR       C              ;  clear carry bit
          MOV       A,R3           ;  load high FCS byte
          RRC       A              ;  shift right
          MOV       R3,A           ;  store shifted high FCS
          MOV       A,R7           ;  load low FCS byte
          RRC       A              ;  shift and pull in bit for FCS high
          MOV       R7,A           ;  store shifted low FCS
          JNB       RM,brf1        ;  if lsb of low FCS = 0, jump to brf1
          CPL       C              ;  else complement carry bit
brf1:     JNC       brf2           ;  if RM XOR (low FCS lsb) = 0 jump to brf2
          MOV       A,R3           ;  else load high FCS
          XRL       A,#FCSH        ;  and XOR with high FCS poly
          MOV       R3,A           ;  store high FCS
          MOV       A,R7           ;  load low FCS
          XRL       A,#FCSL        ;  XOR with low FCS poly
          MOV       R7,A           ;  store low FCS
brf2:     DJNZ      RMLPC,brf0     ;  loop through bits in message byte
brfcs_d:  RET                      ;  done this pass

a_rfcs:   MOV       A,R3           ;  load FCS high
          XRL       A,#FCVH        ;  compare with 0F0H
          JNZ       arf0           ;  if <> 0 jump to arf0
          MOV       A,R7           ;  load FCS low
          XRL       A,#FCVL        ;  else compare with 0B8H
          JNZ       arf0           ;  if <> 0 jump to arf0
          CLR       RFRCV          ;  else turn FCS LED on
          SETB      OKFLG          ;  set FCS OK flag
arf0:     MOV       R3,#FCSS       ;  reseed FCS high
          MOV       R7,#FCSS       ;  reseed FCS low
arfcs_d:  RET                      ;  RX FCS done

srio:     PUSH      PSW            ;  save
          PUSH      ACC            ;  environment
          JNB       TI,sr_0        ;  skip if not TI flag
          CLR       TI             ;  else clear TI flag
sr_0:     JNB       RI,sr_1        ;  skip if not RI flag
          CLR       RI             ;  and clear RI flag
          JNB       SIFLG,sr_1     ;  skip if serial in inactive
          CLR       PCRCV          ;  else turn PC LED on
          ACALL     do_tx          ;  get & transmit message from host
          SETB      PCRCV          ;  turn PC LED off
sr_1:     POP       ACC            ;  restore
          POP       PSW            ;  environment
          RET                      ;  serial in done

do_as:    CLR       PLLON          ;  idle RX PLL
          ACALL     hello2         ;  get AutoSend message
          ACALL     txfcs          ;  build and add FCS
          ACALL     txpre          ;  send TX preamble
          ACALL     txmsg          ;  send TX message
          ACALL     txrst          ;  reset TX
          SETB      PLLON          ;  enable RX PLL
          RET                      ;  TX message done

do_tx:    ACALL     txget          ;  get TX message from host
          JNB       TXFLG,do1      ;  skip if send TX idle
          CLR       PLLON          ;  else idle RX PLL
          ACALL     txfcs          ;  build and add FCS
          ACALL     txpre          ;  send TX preamble
          ACALL     txmsg          ;  send TX message
          INC       TXCNT          ;  increment TX count
do1:      ACALL     txrst          ;  reset TX
          SETB      PLLON          ;  enable RX PLL
          RET                      ;  TX message done

do_rt:    CLR       PLLON          ;  idle RX PLL
          ACALL     txpre          ;  send TX preamble
          ACALL     txmsg          ;  send TX message
          INC       TXCNT          ;  increment TX count
          ACALL     txrst          ;  reset TX
          SETB      PLLON          ;  enable RX PLL
          RET                      ;  TX message done

txget:    MOV       A,SBUF         ;  get byte
          MOV       TMBYT,A        ;  copy to TMBYT
          XRL       A,#FEND        ;  compare to FEND
          JZ        txg0           ;  if FEND jump to txg0
          AJMP      txg_d          ;  else done
txg0:     MOV       @R1,TMBYT      ;  store 1st FEND
          INC       TMBYC          ;  bump TX byte counter
txg1:     MOV       TMFCC,#0       ;  reset timeout counter
          SETB      TOFLG          ;  set timeout flag
          CLR       RI             ;  clear RI flag
txg2:     JNB       TOFLG,txg3     ;  if TOFLG reset jump to txg3
          JNB       RI,txg2        ;  else loop until next byte
          CLR       RI             ;  clear RI flag
          CLR       TOFLG          ;  clear TOFLG
          AJMP      txg4           ;  and jump to txg4
txg3:     MOV       TMBYC,#2       ;  look like null message
          AJMP      txg6           ;  and jump to txg6
txg4:     MOV       A,SBUF         ;  get byte
          MOV       TMBYT,A        ;  copy to TMBYT
          INC       TMBYC          ;  bump byte counter
          INC       R1             ;  bump pointer R1
          MOV       @R1,TMBYT      ;  store byte
          MOV       A,TMBYC        ;  load counter
          CLR       C              ;  clear carry
          SUBB      A,#28          ;  test for 28 bytes
          JZ        txg5           ;  if 28 handle overflow at txg5
          MOV       A,TMBYT        ;  else load byte
          CJNE      A,#FEND,txg1   ;  if <> FEND loop to txg1
          AJMP      txg6           ;  else jump to txg6 on 2nd FEND
txg5:     MOV       @R1,#FEND      ;  force 2nd FEND
txg6:     MOV       R1,#TXMB       ;  reset TX message pointer
          MOV       A,TMBYC        ;  get byte count
          CJNE      A,#2,txg7      ;  if <> 2 jump to txg7
          MOV       TMBYC,#0       ;  else reset byte counter
          AJMP      txg_d          ;  jump to txg_d
txg7:     CLR       SIFLG          ;  idle serial in
          CLR       TOFLG          ;  clear timeout flag
          SETB      TXFLG          ;  set TX active flag
          MOV       TFBUF,TFTX     ;  update local TO/FROM buffer
          MOV       IDBUF,IDTX     ;  update local ID buffer
          CLR       TI             ;  clear TI flag
          MOV       SBUF,#FEND     ;  send 1st FEND
txg8:     JNB       TI,txg8        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          MOV       SBUF,#255      ;  send PAK byte
txg9:     JNB       TI,txg9        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
          MOV       SBUF,#FEND     ;  send 2nd FEND
txgA:     JNB       TI,txgA        ;  wait until byte sent
          CLR       TI             ;  clear TI flag
txg_d:    RET                      ;  get TX message done

txfcs:    INC       TMBYC          ;  # bytes including FCS
          MOV       @R1,TMBYC      ;  replace 1st FEND with # bytes
          MOV       TMFCC,TMBYC    ;  move byte count to loop counter
          DEC       TMFCC          ;  loop count is 2 less
          DEC       TMFCC          ;  than # bytes including FCS
txf0:     MOV       TMFCS,@R1      ;  get next message byte
          INC       R1             ;  bump pointer
          ACALL     b_tfcs         ;  build FCS
          DJNZ      TMFCC,txf0     ;  loop for next byte
          ACALL     a_tfcs         ;  add FCS
          MOV       R1,#TXMB       ;  reset TX message pointer
          JB        ASFLG,txf1     ;  skip if AutoSend
          MOV       DPTR,#delay    ;  point to delay table
          MOV       A,TL1          ;  get random table offset
          ANL       A,#07H         ;  mask upper 5 bits
          MOVC      A,@A+DPTR      ;  load table byte
          MOV       TXTH,A         ;  into TX delay high
          AJMP      txf2           ;  skip AutoSend delay
txf1:     MOV       TXTH,#TXR0     ;  load AutoSend delay
txf2:     MOV       TXTL,#0        ;  clear TX delay low
          SETB      TMFLG          ;  set TX message flag
txf_d:    RET                      ;  TX FCS done

txpre:    CLR       PTT            ;  turn PTT on
          MOV       B,#200         ;  load PTT delay count
txp0:     DJNZ      B,txp0         ;  loop to delay
txp1:     MOV       DPTR,#tstrt    ;  point to TX start table
          MOV       B,#0           ;  clear B
          MOV       A,B            ;  B holds table offset
          MOVC      A,@A+DPTR      ;  load table entry
          MOV       TMBYT,A        ;  into TMBYT
          MOV       TMBIC,#4       ;  load bit count
          MOV       TXSMC,#0       ;  clear sample count
          SETB      TSFLG          ;  turn TX sample out on
txp2:     MOV       A,TXSMC        ;  get sample count
          JNZ       txp2           ;  loop until sample count 0
          MOV       A,TMBIC        ;  get bit count
          JNZ       txp3           ;  if <> 0 jump to txp3
          MOV       A,B            ;  else get current offset (0 to 11)
          CLR       C              ;  clear carry
          SUBB      A,#11          ;  subtract ending offset
          JZ        txp_d          ;  if 0  done
          INC       B              ;  else bump byte count
          MOV       A,B            ;  get count/offset
          MOVC      A,@A+DPTR      ;  load table entry
          MOV       TMBYT,A        ;  into TMBYT
          MOV       TMBIC,#4       ;  reload bit count
txp3:     MOV       A,TMBYT        ;  get TX message byte
          CLR       C              ;  clear carry
          RRC       A              ;  shift right into carry
          MOV       TXBIT,C        ;  load next bit
          MOV       TMBYT,A        ;  store shifted message byte
          DEC       TMBIC          ;  decrement bit count
          MOV       TXSMC,#8       ;  reload sample count
          AJMP      txp2           ;  loop again
txp_d:    RET                      ;  TX preamble done

txmsg:    MOV       B,#1           ;  count 1st byte sent
          MOV       A,@R1          ;  get 1st TX message byte
          MOV       TMBYT,A        ;  into TMBYT
          MOV       DPTR,#smbl     ;  point to symbol table
          ANL       A,#0FH         ;  clean offset
          MOVC      A,@A+DPTR      ;  get 6-bit symbol
          MOV       TXSL,A         ;  move to TXSL
          MOV       A,TMBYT        ;  get TMBYT
          SWAP      A              ;  swap nibbles
          ANL       A,#0FH         ;  clean offset
          MOVC      A,@A+DPTR      ;  get 6-bit symbol
          MOV       TXSH,A         ;  move to TXSH
          MOV       TMBIC,#12      ;  set bit count to 12
          MOV       TXSMC,#0       ;  clear sample count
txm0:     MOV       A,TXSMC        ;  get sample count
          JNZ       txm0           ;  loop until sample count 0
          MOV       A,TMBIC        ;  get bit count
          CLR       C              ;  clear carry
          SUBB      A,#7           ;  subtract 7 
          JNC       txm1           ;  if => 7 jump to txm1
          MOV       A,TMBIC        ;  else get bit count
          JNZ       txm2           ;  if > 0 jump to txm2
          MOV       A,B            ;  else get current byte number
          CLR       C              ;  clear carry
          SUBB      A,TMBYC        ;  subtract TX message byte count
          JZ        txm3           ;  if 0  done
          INC       R1             ;  else bump byte pointer
          INC       B              ;  and bump byte counter
          MOV       A,@R1          ;  get next byte
          MOV       TMBYT,A        ;  into TMBYT
          MOV       DPTR,#smbl     ;  point to symbol table
          ANL       A,#0FH         ;  offset
          MOVC      A,@A+DPTR      ;  get 6-bit symbol
          MOV       TXSL,A         ;  move to TXSL
          MOV       A,TMBYT        ;  get TMBYT
          SWAP      A              ;  swap nibbles
          MOV       DPTR,#smbl     ;  point to symbol table
          ANL       A,#0FH         ;  clean offset
          MOVC      A,@A+DPTR      ;  get 6-bit symbol
          MOV       TXSH,A         ;  move to TXSH
          MOV       TMBIC,#12      ;  set bit count to 12
txm1:     MOV       A,TXSL         ;  get low TX symbol
          CLR       C              ;  clear carry
          RRC       A              ;  shift right into carry
          MOV       TXBIT,C        ;  load next bit
          MOV       TXSL,A         ;  store shifted message byte
          DEC       TMBIC          ;  decrement bit count
          MOV       TXSMC,#8       ;  reload sample count
          AJMP      txm0           ;  loop again
txm2:     MOV       A,TXSH         ;  get high TX symbol
          CLR       C              ;  clear carry
          RRC       A              ;  shift right into carry
          MOV       TXBIT,C        ;  load next bit
          MOV       TXSH,A         ;  store shifted message byte
          DEC       TMBIC          ;  decrement bit count
          MOV       TXSMC,#8       ;  reload sample count
          AJMP      txm0           ;  loop again
txm3:     CLR       TSFLG          ;  clear TX sample out flag
          CLR       TXPIN          ;  clear TX out pin
          SETB      PTT            ;  turn PTT off
txm_d:    RET                      ;  TX message done

txrst:    CLR       TMFLG          ;  clear TX message flag
          CLR       AMFLG          ;  clear AutoSend message flag
          CLR       A              ;  reset for next TX
          MOV       TMBYT,A        ;  clear TX message byte
          MOV       TMFCC,A        ;  clear TX FCS count
          MOV       TXSMC,A        ;  clear TX out count
          MOV       TXSL,A         ;  clear TX symbol low
          MOV       TXSH,A         ;  clear TX symbol high
          MOV       R1,#TXMB       ;  point R1 to message start
          JB        ASFLG,txr_d    ;  skip if in AutoSend
          JB        TXFLG,txr_d    ;  skip if send TX active
          MOV       TMBYC,A        ;  reset TX message byte count
          MOV       TXCNT,A        ;  reset TX retry count
          MOV       TXTL,A         ;  clear TX timer low
          MOV       TXTH,A         ;  clear TX timer high
          SETB      SIFLG          ;  enable serial in
txr_d:    RET                      ;  TX reset done

b_tfcs:   MOV       B,#8           ;  load loop count of 8
btf0:     CLR       C              ;  clear carry bit
          MOV       A,TMFCS        ;  load TX message byte
          RRC       A              ;  shift lsb into carry
          MOV       TMFCS,A        ;  store shifted message byte
          MOV       TM,C           ;  load TM with lsb
          CLR       C              ;  clear carry bit
          MOV       A,R5           ;  load high FCS byte
          RRC       A              ;  shift right
          MOV       R5,A           ;  store shifted high FCS
          MOV       A,R6           ;  load low FCS byte
          RRC       A              ;  shift and pull in bit for FCS high
          MOV       R6,A           ;  store shifted low FCS
          JNB       TM,btf1        ;  if lsb of low FCS = 0, jump to btf1
          CPL       C              ;  else complement carry bit
btf1:     JNC       btf2           ;  if TM XOR (low FCS lsb) = 0 jump to btf2
          MOV       A,R5           ;  else load high FCS
          XRL       A,#FCSH        ;  and XOR with high FCS poly
          MOV       R5,A           ;  store high FCS
          MOV       A,R6           ;  load low FCS
          XRL       A,#FCSL        ;  XOR with low FCS poly
          MOV       R6,A           ;  store low FCS
btf2:     DJNZ      B,btf0         ;  loop through bits in message byte
btfcs_d:  RET                      ;  done this pass

a_tfcs:   MOV       A,R6           ;  load FCS (high/low switch)
          CPL       A              ;  1's complement
          MOV       @R1,A          ;  store at end of TX message
          INC       R1             ;  increment TX message byte pointer
          MOV       A,R5           ;  load FCS (high/low switch)
          CPL       A              ;  1's complement
          MOV       @R1,A          ;  store at end of TX message
          MOV       R5,#FCSS       ;  reseed FCS high
          MOV       R6,#FCSS       ;  reseed FCS low
atfcs_d:  RET                      ;  add TX FCS done

setup:    CLR       EA             ;  disable interrupts
          SETB      PTT            ;  turn PTT off
          CLR       TXPIN          ;  turn TX modulation off
tick_su:  MOV       TMOD,#ITMOD    ;  set timers T0 and T1 to mode 2
          CLR       TR0            ;  stop timer T0
          CLR       TF0            ;  clear T0 overflow
          MOV       TH0,#ITICK     ;  load count for 62.40 us tick
          MOV       TL0,#ITICK     ;  load count for 62.40 us tick
          SETB      TR0            ;  start timer T0
          SETB      ET0            ;  unmask T0 interrupt
uart_su:  SETB      MAX            ;  power up Maxim RS232 converter
          CLR       TR1            ;  stop timer T1
          CLR       TF1            ;  clear T1 overflow
          MOV       TH1,#IBAUD     ;  load baud rate count
          MOV       TL1,#IBAUD     ;  load baud rate count
          MOV       PCON,#ISMOD    ;  SMOD = 1 for baud rate @ 22.1184 MHz
          SETB      TR1            ;  start baud rate timer T1
          MOV       SCON,#ISCON    ;  enable UART mode 1
          MOV       A,SBUF         ;  clear out UART RX buffer
          CLR       A              ;  clear A
          CLR       RI             ;  clear RI (byte received) flag
          CLR       TI             ;  clear TI (byte sent) flag
          ACALL     hello          ;  send start up message
          ACALL     initr          ;  initialize TX & RX
          MOV       TXTH,#TXR0     ;  load default AutoSend delay
          SETB      SIFLG          ;  set serial in flag active
          MOV       C,ID3          ;  read ID3
          JC        as_set         ;  skip if no ID3 jumper
          SETB      NHFLG          ;  else set no FEND/header flag
as_set:   MOV       C,ID0          ;  read ID0
          JC        ser_on         ;  skip if no ID0 jumper
          ACALL     hello2         ;  else do AutoSend
ser_on:   SETB      ES             ;  enable serial ISR
isr_on:   SETB      EA             ;  enable interrupts
          SETB      PLLON          ;  activate RX PLL
setup_d:  RET                      ;  setup done

initr:    ANL       BOOT,#1        ;  warm boot (don't reset WBFLG)
          MOV       R0,#35         ;  starting here
          MOV       B,#93          ;  for 93 bytes
          CLR       A              ;  clear A
clr_r:    MOV       @R0,A          ;  clear RAM
          INC       R0             ;  bump RAM pointer
          DJNZ      B,clr_r        ;  loop again
          MOV       R0,#RXMB       ;  load RX buffer pointer
          MOV       R1,#TXMB       ;  load TX buffer pointer
          MOV       R2,A           ;  clear R2
          MOV       R3,#FCSS       ;  seed R3
          MOV       R5,#FCSS       ;  seed R5
          MOV       R6,#FCSS       ;  seed R6
          MOV       R7,#FCSS       ;  seed R7
          MOV       TFBUF,#34      ;  initialize TO/FROM 2 & 2
          MOV       IDBUF,#3       ;  initialize ID = 3
          CLR       SOPFLG         ;  clear SOPFLG
          SETB      PT0            ;  tick is 1st priority
ini_d:    RET                      ;  done

hello:    MOV       DPTR,#table    ;  point to table
          MOV       B,#13          ;  load loop count in B
          MOV       R7,#0          ;  R7 has 1st table entry
snd_h:    MOV       A,R7           ;  move table offset into A
          MOVC      A,@A+DPTR      ;  load table byte
          CLR       TI             ;  clear TI flag
          MOV       SBUF,A         ;  send byte
nxt_tx:   JNB       TI,nxt_tx      ;  wait until sent
          INC       R7             ;  bump index
          DJNZ      B,snd_h        ;  loop to send message
hello_d:  RET                      ;  done

hello2:   MOV       DPTR,#tbl_2    ;  point to table 2
          MOV       R1,#TXMB       ;  reset TX buffer pointer
          MOV       B,#10          ;  loop count for 9 bytes
          MOV       TMBYC,#0       ;  offset for 1st table entry
snd_h2:   MOV       A,TMBYC        ;  move table offset into A
          MOVC      A,@A+DPTR      ;  load table byte
          MOV       @R1,A          ;  into TX buffer
          INC       TMBYC          ;  increment TMBYC
          INC       R1             ;  increment R1
          DJNZ      B,snd_h2       ;  loop to load message
          MOV       R1,#TXMB       ;  reset TX pointer
          CLR       SIFLG          ;  reset serial input
          SETB      ASFLG          ;  set AutoSend flag
helo2_d   RET

;  tables:

tstrt:    .BYTE     10             ;  preamble/SOP table
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     10             ;  table data
          .BYTE     8              ;  table data
          .BYTE     3              ;  table data
          .BYTE     11             ;  table data

smbl:     .BYTE     13             ;  4-to-6 bit table
          .BYTE     14             ;  table data
          .BYTE     19             ;  table data
          .BYTE     21             ;  table data
          .BYTE     22             ;  table data
          .BYTE     25             ;  table data
          .BYTE     26             ;  table data
          .BYTE     28             ;  table data
          .BYTE     35             ;  table data
          .BYTE     37             ;  table data
          .BYTE     38             ;  table data
          .BYTE     41             ;  table data
          .BYTE     42             ;  table data
          .BYTE     44             ;  table data
          .BYTE     50             ;  table data
          .BYTE     52             ;  table data
          .BYTE     00             ;  overflow

delay:    .BYTE     020H           ;  0.50 second
          .BYTE     044H           ;  1.10 second
          .BYTE     032H           ;  0.80 second
          .BYTE     058H           ;  1.40 second
          .BYTE     028H           ;  0.65 second
          .BYTE     04EH           ;  1.25 second
          .BYTE     03CH           ;  0.95 second
          .BYTE     062H           ;  1.55 second

table:    .BYTE     192            ;  start up message
          .BYTE     34             ;  table data
          .BYTE     3              ;  table data
          .BYTE     'D'            ;  table data
          .BYTE     'K'            ;  table data
          .BYTE     '2'            ;  table data
          .BYTE     '0'            ;  table data
          .BYTE     '0'            ;  table data
          .BYTE     'A'            ;  table data
          .BYTE     ':'            ;  table data
          .BYTE     ' '            ;  table data
          .BYTE     ' '            ;  table data
          .BYTE     192            ;  table data

tbl_2:    .BYTE     192            ;  table data
          .BYTE     34             ;  table data
          .BYTE     3              ;  table data
          .BYTE     'H'            ;  table data
          .BYTE     'e'            ;  table data
          .BYTE     'l'            ;  table data
          .BYTE     'l'            ;  table data
          .BYTE     'o'            ;  table data
          .BYTE     ' '            ;  table data
          .BYTE     192            ;  table data

          .END                     ;  end of source code

