Indirect Addressing?
beardcm
Posts: 12
I'm having trouble understanding·what this command in the sendstring2 subroutine really does in relation to the addressing:
mov·w,#STRINGS_ORG>>8
**refer to code above**
mov·w,#STRINGS_ORG>>8
**refer to code above**
Comments
Program Code:
SX28AC
TEST1
················································································
SX_Key
; ** Baud Rates for UART 1 **
U1B1200 ;baud rate of 1.2 Kbps
; ** Baud Rates for UART 2· **
U2B9600 ;baud rate of 9.6 kbps
IFDEF SX_Key ;SX-Key Directives
· IFDEF SX28AC ;SX28AC device directives for SX-Key
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
· IFDEF SX48_52 ;SX48/52/BD device directives for SX-Key
device oschs2
· ENDIF
freq 50_000_000
ELSE · ;SASM Directives
·
· IFDEF SX28AC ;SX28AC device directives for SASM
device SX28,oschs2,turbo,stackx,optionx
· ENDIF
·
· IFDEF SX48_52 ;SX48BD or SX52BD device directives for SASM
device SX52,oschs2·
· ENDIF
ENDIF
id '2UART VP' ;
reset resetEntry ; set reset vector
IRC_CAL IRC_FAST
;*********************************************************************************************
;
Macro's
; Macro: _bank
; Sets the bank appropriately for all revisions of SX.
;
; This is required since the bank instruction has only a 3-bit
operand, it cannot be used to
; access all 16 banks of the SX48/52.· FSR.7 (SX48/52bd production
release) needs to be set
; appropriately, depending on the bank address being accessed. This
macro fixes this.
;
; So, instead of using the bank instruction to switch between banks,
use _bank instead.
;*********************************************************************************************
_bank macro 1
· noexpand
bank \1
IFDEF SX48_52
·· IF \1 & %10000000 ;SX48BD and SX52BD (production release) bank
instruction
· expand
setb fsr.7 ;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by
software.
· noexpand
··· ·· ELSE
· expand
clrb fsr.7
· noexpand
········· ENDIF
ENDIF
endm
;*********************************************************************************************
; Macro: _mode
; Sets the MODE register appropriately for all revisions of SX.
;
; This is required since the MODE (or MOV M,#) instruction has only a
4-bit operand.
; The SX28AC use only 4 bits of the MODE register, however the
SX48/52BD have
; the added ability of reading or writing some of the MODE registers,
and therefore use
; 5-bits of the MODE register. The· MOV M,W instruction modifies all
8-bits of the
; MODE register, so this instruction must be used on the SX48/52BD to
make sure the MODE
; register is written with the correct value. This macro fixes this.
;
; So, instead of using the MODE or MOV M,# instructions to load the M
register, use
;· _mode instead.
;*********************************************************************************************
_mode macro 1
· noexpand
IFDEF SX48_52
· expand
mov w,#\1·········· ;loads the M register correctly for the SX48BD
and SX52BD
mov m,w
· noexpand
ELSE
· expand
mov m,#\1··· ;loads the M register correctly for the SX18AC, SX20AC
;and SX28AC
· noexpand
ENDIF
endm
;*********************************************************************************************
······· ; INCP/DECP macros for incrementing/decrementing pointers to
RAM
······· ; used to compensate for incompatibilities between SX28AC and
SX52BD
;*********************************************************************************************
INCP macro 1 ; Increments a pointer to RAM
inc··· \1
IFNDEF SX48_52
setb· \1.4 ; If SX18 or SX28AC,keep bit 4 of the pointer = 1
ENDIF ; to jump from $1f to $30,etc
endm
DECP macro 1 ; Decrements a pointer to RAM
IFDEF SX48_52
dec··· \1
ELSE
clrb·· \1.4 ; If SX18 or SX28AC, forces rollover to next bank
dec··· \1 ; if it rolls over. (skips banks with bit 4 = 0)
setb·· \1.4············ ; Eg: $30 ---> $20 ---> $1f ---> $1f
ENDIF·························· ; AND: $31 ---> $21 ---> $20 ---> $30
endm
;*********************************************************************************************
······· ; Error generating macros
······· ; Used to generate an error message if the label is
intentionally moved into the second page.
······· ; Use for lookup tables.
;*********************************************************************************************
tablestart macro 0 ; Generates an error message if code that MUST be
in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
tableEnd macro 0 ; Generates an error message if code that MUST be in
; the first half of a page is moved into the second half
if $ & $100
ERROR····· 'Must be located in the first half of a page.'
endif
endm
;*********************************************************************************************
;
Memory Organization
;*********************************************************************************************
;*********************************************************************************************
;
Data Memory address
definitions
; These definitions ensure the proper address is used for banks 0 - 7
for 2K SX devices
; (SX28) and 4K SX devices (SX48/52).
;*********************************************************************************************
IFDEF SX48_52
global_org = $0A
bank0_org = $00
bank1_org = $10
bank2_org = $20
bank3_org = $30
bank4_org = $40
bank5_org = $50
bank6_org = $60
bank7_org = $70
ELSE
global_org = $08
bank0_org = $10
bank1_org = $30
bank2_org = $50
bank3_org = $70
bank4_org = $90
bank5_org = $B0
bank6_org = $D0
bank7_org = $F0
ENDIF
;*********************************************************************************************
;
Global Register
definitions
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on
SX18/20/28.
;*********************************************************************************************
org···· global_org
flags0 equ global_org + 0 ; stores bit-wise operators like flags
; and function-enabling bits (semaphores)
;
VP: RS232
Receive
rs232Tx1Flag equ flags0.0 ;indicates that UART1 is transmitting if set
or not transmitting if reset
rs232Tx2Flag equ flags0.1 ;indicates that UART2 is transmitting if set
or not transmitting if reset
rs232Rx1Flag equ flags0.2 ;indicates that UART1 has received a byte if
set
rs232Rx2Flag equ flags0.3 ;indicates that UART2 has received a byte if
set
isrTemp0 equ global_org + 1 ; Interrupt Service Routine's temp
register.·
; Don't use this register in the mainline.
localTemp0 equ global_org + 2 ; temporary storage register
; Used by first level of nesting
; Never guaranteed to maintain data
localTemp1 equ global_org + 3 ; temporary storage register
; Used by second level of nesting
; or when a routine needs more than one
; temporary global register.
localTemp2 equ global_org + 4 ; temporary storage register
; Used by third level of nesting or by
; main loop routines that need a loop
; counter, etc.
;*********************************************************************************************
;
RAM Bank Register
definitions
;*********************************************************************************************
;*********************************************************************************
; Bank 0
;*********************************************************************************
org···· bank0_org
bank0 = $
;*********************************************************************************
; Bank 1
;*********************************************************************************
org···· bank1_org
bank1 = $
rs232TxBank =······ $ ;UART Transmit bank
rs232Tx1High ds····· 1 ;High Byte to be· transmitted
rs232Tx1Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx1Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx1Divide ds····· 1 ;xmit timing counter
rs232Tx1Byte ds 1 ;store the byte to be sent in this buffer
rs232Tx2High ds····· 1 ;High Byte to be· transmitted
rs232Tx2Low ds····· 1 ;Low· Byte to be transmitted
rs232Tx2Count ds····· 1 ;counter to keep track of the bits sent
rs232Tx2Divide ds····· 1 ;xmit timing counter
rs232Tx2Byte ds 1 ;store the byte to be sent in this buffer
MultiplexBank = $ ;Multipler Bank
isrMultiplex · ds····· 1· ;Used to jump between the ISR Threads when
; an Interrupt occurs
;*********************************************************************************
; Bank 2
;*********************************************************************************
org···· bank2_org
bank2 = $
rs232RxBank = $
rs232Rx1Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx1Divide ds····· 1 ;receive timing counter
rs232Rx1Byte ds····· 1 ;buffer for incoming byte
rs232Byte1 ds 1 ;Used by serial routines
rs232Rx2Count ds····· 1 ;counter to keep track of the number of bits
received
rs232Rx2Divide ds····· 1 ;receive timing counter
rs232Rx2Byte ds····· 1 ;buffer for incoming byte
rs232Byte2 ds 1 ;used by serial routines
;*********************************************************************************
; Bank 3
;*********************************************************************************
org···· bank3_org
bank3 = $
;*********************************************************************************
; Bank 4
;*********************************************************************************
org···· bank4_org
bank4 = $
;*********************************************************************************
; Bank 5
;*********************************************************************************
org···· bank5_org
bank5 = $
;*********************************************************************************
; Bank 6
;*********************************************************************************
org···· bank6_org
bank6 = $
;*********************************************************************************
; Bank 7
;*********************************************************************************
org···· bank7_org
bank7 = $
IFDEF SX48_52
;*********************************************************************************
; Bank 8
;*********************************************************************************
org $80 ;bank 8 address on SX52
bank8 = $
;*********************************************************************************
; Bank 9
;*********************************************************************************
org $90 ;bank 9 address on SX52
bank9 = $
;*********************************************************************************
; Bank A
;*********************************************************************************
org $A0 ;bank A address on SX52
bankA = $
;*********************************************************************************
; Bank B
;*********************************************************************************
org $B0 ;bank B address on SX52
bankB = $
;*********************************************************************************
; Bank C
;*********************************************************************************
org $C0 ;bank C address on SX52
bankC = $
;*********************************************************************************
; Bank D
;*********************************************************************************
org $D0 ;bank D address on SX52
bankD = $
;*********************************************************************************
; Bank E
;*********************************************************************************
org $E0 ;bank E address on SX52
bankE = $
;*********************************************************************************
; Bank F
;*********************************************************************************
org $F0 ;bank F address on SX52
bankF = $
ENDIF
;*****************************************************************************************
;
Port Assignment
;*****************************************************************************************
RA_latch equ %00000000 ;SX28/48/52 port A latch init ;intial value
after reset
RA_DDIR equ %11111111 ;SX28/48/52 port A DDIR value ;0=Output,1=Input
RA_LVL equ %00000000 ;SX28/48/52 port A LVL value ;0=CMOS,1=TTL
RA_PLP equ %00000000 ;SX28/48/52 port A PLP value ;0=Enable,1=Disable
RB_latch equ %10001000 ;SX28/48/52 port B latch init ;intial value
after reset
RB_DDIR equ %01110111 ;SX28/48/52 port B DDIR value ;0=Output,1=Input
RB_ST equ %11111111 ;SX28/48/52 port B ST value ;0=Enable,1=Disable
RB_LVL equ %00000000 ;SX28/48/52 port B LVL value ;0=CMOS,1=TTL
RB_PLP equ %11001100 ;SX28/48/52 port B PLP value ;0=Enable,1=Disable
RC_latch equ %00000000 ;SX28/48/52 port C latch init ;intial value
after reset
RC_DDIR equ %11111111 ;SX28/48/52 port C DDIR value ;0=Output,1=Input
RC_ST equ %11111111 ;SX28/48/52 port C ST value ;0=Enable,1=Disable
RC_LVL equ %00000000 ;SX28/48/52 port C LVL value ;0=CMOS,1=TTL
RC_PLP equ %00000000 ;SX28/48/52 port C PLP value ;0=Enable,1=Disable
IFDEF SX48_52
RD_latch equ %00000000 ;SX48/52 port D latch init ;intial value after
reset
RD_DDIR equ %11111111 ;SX48/52 port D DDIR value ;0=Output,1=Input
RD_ST equ %11111111 ;SX48/52 port D ST value ;0=Enable,1=Disable
RD_LVL equ %00000000 ;SX48/52 port D LVL value ;0=CMOS,1=TTL
RD_PLP equ %00000000 ;SX48/52 port D PLP value ;0=Enable,1=Disable
RE_latch equ %00000000 ;SX48/52 port E latch init ;intial value after
reset
RE_DDIR equ %11111111 ;SX48/52 port E DDIR value ;0=Output,1=Input
RE_ST equ %11111111 ;SX48/52 port E ST value ;0=Enable,1=Disable
RE_LVL equ %00000000 ;SX48/52 port E LVL value ;0=CMOS,1=TTL
RE_PLP equ %00000000 ;SX48/52 port E PLP value ;0=Enable,1=Disable
ENDIF
;*********************************************************************************************
;
Pin Definitions
;*********************************************************************************************
rs232Rxpin1····· equ···· rb.6 ;UART1 receive input
rs232Txpin1····· equ···· rb.7 ;UART1 transmit output
rs232Rxpin2····· equ···· rb.2 ;UART2 receive input
rs232Txpin2····· equ···· rb.3 ;UART2 transmit output
;*********************************************************************************************
;
Program constants
;*********************************************************************************************
;*********************************************************************************************
; UART Constants values
;*********************************************************************************************
intPeriod = 217
UARTfs = 230400
Num = 4 ; Number of times ISR thread1 is called in the
; ISRMultiplexer
IFDEF· U1B1200
UARTBaud1 = 1200
ENDIF
IFDEF· U1B2400
UARTBaud1 = 2400
ENDIF
IFDEF· U1B4800
UARTBaud1 = 4800
ENDIF
IFDEF· U1B9600
UARTBaud1 = 9600
ENDIF
IFDEF· U1B1920
UARTBaud1 = 19200
ENDIF
IFDEF· U1B5760
UARTBaud1 = 57600
ENDIF
UARTDivide1 = (UARTfs/(UARTBaud1*Num)) ;48
UARTStDelay1 = UARTDivide1 +(UARTDivide1/2)+1
IFDEF· U2B1200
UARTBaud2 = 1200
ENDIF
IFDEF· U2B2400
UARTBaud2 = 2400
ENDIF
IFDEF· U2B4800
UARTBaud2 = 4800
ENDIF
IFDEF· U2B9600
UARTBaud2 = 9600
ENDIF
IFDEF· U2B1920
UARTBaud2 = 19200
ENDIF
IFDEF· U2B5760
UARTBaud2 = 57600
ENDIF
UARTDivide2 = (UARTfs/(UARTBaud2*Num)) ;6
UARTStDelay2 = UARTDivide2 +(UARTDivide2/2)+1
IFDEF SX48_52
;*********************************************************************************************
; SX48BD/52BD Mode addresses
; *On SX48BD/52BD, most registers addressed via mode are read and
write, with the
; exception of CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Timer (read) addresses
TCPL_R equ $00 ;Read Timer Capture register low byte
TCPH_R equ $01 ;Read Timer Capture register high byte
TR2CML_R equ $02 ;Read Timer R2 low byte
TR2CMH_R equ $03 ;Read Timer R2 high byte
TR1CML_R equ $04 ;Read Timer R1 low byte
TR1CMH_R equ $05 ;Read Timer R1 high byte
TCNTB_R equ $06 ;Read Timer control register B
TCNTA_R equ $07 ;Read Timer control register A
;
Exchange addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_R equ $0A ;Read MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_R equ $0B ;Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_R equ $0C ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_R equ $0D ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_R equ $0E ;Read Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_R equ $0F ;Read Port Direction
;
Timer (write)
addresses
CLR_TMR equ $10 ;Resets 16-bit Timer
TR2CML_W equ $12 ;Write Timer R2 low byte
TR2CMH_W equ $13 ;Write Timer R2 high byte
TR1CML_W equ $14 ;Write Timer R1 low byte
TR1CMH_W equ $15 ;Write Timer R1 high byte
TCNTB_W equ $16 ;Write Timer control register B
TCNTA_W equ $17 ;Write Timer control register A
;
Port setup (write)
addresses
WKED_W equ $1A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $1B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $1C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $1D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $1E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $1F ;Write Port Direction
ELSE
;*********************************************************************************************
; SX28AC Mode addresses
; *On SX28, all registers addressed via mode are write only, with the
exception of
; CMP and WKPND which do an exchange with W.
;*********************************************************************************************
;
Exchange
addresses
CMP equ $08 ;Exchange Comparator enable/status register with W
WKPND equ $09 ;Exchange MIWU/RB Interrupts pending with W
;
Port setup (read)
addresses
WKED_W equ $0A ;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 =
rising
WKEN_W equ $0B ;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 =
disabled
ST_W equ $0C ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
LVL_W equ $0D ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
PLP_W equ $0E ;Write Port Schmitt Trigger setup, 0 = enabled, 1 =
disabled
DDIR_W equ $0F ;Write Port Direction
ENDIF
;*********************************************************************************************
;
Program memory ORG defines
;*********************************************************************************************
INTERRUPT_ORG equ $0 ; Interrupt must always start at location zero
RESETENTRY_ORG equ $1FB ; The program will jump here on reset
SUBROUTINES_ORG equ $200 ; The subroutines are in this location
STRINGS_ORG equ $300 ; The strings are in the location $300
PAGE3_ORG equ $400 ; Page 3 is empty
MAINPROGRAM_ORG equ $600 ; The main program is in the lastpage of
program memory
;*********************************************************************************************
org INTERRUPT_ORG······· ; First location in program memory.
;*********************************************************************************************
;*********************************************************************************************
;
Interrupt Service Routine
; Note 1: The interrupt code must always originate at address $0.
; · Interrupt Frequency = (Cycle Frequency / -(retiw value))·
; · For example: With a retiw value of -217 and an oscillator frequency
; · of 50MHz, this code runs every 4.32us.
; Note 2: Mode Register 'M' is not saved in SX 28 but saved in SX 52
when an Interrupt
; · occurs. If the code is to run on a SX 28 and 'M' register is used
in the ISR,
; · then the 'M' register has to be saved at the Start of ISR and
restored at the
; · End of ISR.
;*********************************************************************************************
org···· $0
interrupt ;3
;*********************************************************************************************
; Interrupt
; Interrupt Frequency = (Cycle Frequency / -(retiw value))· For
example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this
code runs
; every 4.32us.
;*********************************************************************************************
;*********************************************************************************************
;
VP:VP
Multitasker
; Virtual Peripheral Multitasker : up to 16 individual threads, each
running at the
; (interrupt rate/16). Change them below:
;Input variable(s): isrmultiplex: variable used to choose threads
;Output variable(s): None,executes the next thread
;Variable(s) affected: isrmultiplex
;Flag(s) affected: None
;Program Cycles: 9 cycles (turbo mode)
;*********************************************************************************************
··············· _bank········· Multiplexbank······· ;
··············· inc··········· isrMultiplex········ ; toggle interrupt
rate
··············· mov··········· w,isrMultiplex······ ;
;*********************************************************************************************
; The code between the tableStart and tableEnd statements MUST be
completely within the first
; half of a page. The routines it is jumping to must be in the same
page as this table.
;*********************************************************************************************
········ tableStart································ ; Start all tables
with this macro
··············· jmp··········· pc+w················ ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread2·········· ;
··············· jmp··········· isrThread3·········· ;·
··············· jmp··········· isrThread4·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread5·········· ;
··············· jmp··········· isrThread6·········· ;·
··············· jmp··········· isrThread7·········· ;
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread8·········· ;
··············· jmp··········· isrThread9·········· ;
··············· jmp··········· isrThread10········· ;·
··············· jmp··········· isrThread1·········· ;
··············· jmp··········· isrThread11········· ;
··············· jmp··········· isrThread12········· ;
··············· jmp··········· isrThread13········· ;
········ tableEnd·································· ; End all tables
with this macro.··
;*********************************************************************************************
;VP: VP Multitasker
; ISR TASKS
;*********************************************************************************************
isrThread1········································· ; Serviced at ISR
rate/4
;*********************************************************************************************
; Virtual Peripheral: Universal Asynchronous Receiver Transmitter
(UART) These routines send
; and receive RS232 serial data, and are currently configured (though
modifications can be
; made) for the popular "No parity-checking, 8 data bit, 1 stop bit"
(N,8,1) data format.
;
; The VP below has 2 UARTS implemented - UART1 & UART2. Both the UARTs
can work at independent
; Baud Rates.
;
; RECEIVING: The rs232Rx1flag & rs232Rx2flag are set high whenever a
valid byte of data has
; been received and it is the calling routine's responsibility to reset
this flag once the
; incoming data has been collected.
;
; TRANSMITTING: The transmit routine requires the data to be inverted
and loaded
; (rs232Txhigh+rs232Txlow) register pair (with the inverted 8 data bits
stored in
; rs232Txhigh and rs232Txlow bit 7 set high to act as a start bit).
Then the number of bits
; ready for transmission (10=1 start + 8 data + 1 stop) must be loaded
into the rs232Txcount
; register. As soon as this latter is done, the transmit routine
immediately begins sending
; the data. This routine has a varying execution rate and therefore
should always be
; placed after any timing-critical virtual peripherals such as timers,
; adcs, pwms, etc.
; Note: The transmit and receive routines are independent and either
may be removed for each
; of the UARTs. The initial "_bank rs232TxBank" & "_bank rs232RxBank"
(common)
; instruction is kept for Transmit & Receive routines.
;······ Input variable(s) : rs232Tx1Low (only high bit used),
rs232Tx1High, rs232Tx1Count
; If rs232Tx1Flag SET, then transmit on UART1
; rs232Tx2Low (only high bit used), rs232Tx2High, rs232Tx2Count
; If rs232Tx2Flag SET, then transmit on UART2
;······ Output variable(s) : rs232Rx1Flag, rs232Rx1Byte
; rs232Rx2Flag, rs232Rx2Byte
;······ Variable(s) affected : rs232Tx1Divide, rs232Rx1Divide,
rs232Rx1Count
; rs232Tx2Divide, rs232Rx2Divide, rs232Rx2Count
;······ Flag(s) affected : rs232Tx1Flag, rs232Tx2Flag
; rs232Rx1Flag, rs232Rx1Flag
; Program cycles: 22 worst case for Tx, 23 worst case for Rx
; Variable Length?· Yes.
;*********************************************************************************************
UART1
rs232Transmit
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx1FLag ;1
jmp rs232Receive1 ;1
decsz rs232Tx1Divide ;1 only execute the transmit routine
jmp rs232Receive1 ;1
mov w,#UARTDivide1 ;1 load UART1 baud rate (50MHz)
mov rs232Tx1Divide,w ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
jmp rs232Receive1 ;1
:txbit clc···························· ;1 yes, ready stop bit
rr····· rs232Tx1High ;1· and shift to next bit
rr····· rs232Tx1Low ;1·
dec···· rs232Tx1Count ;1 decrement bit counter
snb rs232Tx1Low.6 ;1 output next bit
clrb rs232TxPin1 ;1·
sb rs232Tx1Low.6 ;1·
setb rs232TxPin1 ;1·
test··· rs232Tx1Count ;1 are we sending?
snz ;1·
clrb rs232Tx1Flag ;1,22
rs232Receive1
_bank rs232RxBank ;2
······· sb rs232RxPin1 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin1 ;1·
······· stc ;1·
test··· rs232Rx1Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
mov···· rs232Rx1Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay1 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx1Divide,w ;1·
:rxbit········· decsz rs232Rx1Divide ;1 middle of next bit?
········· jmp :rs232RxOut1 ;1
mov w,#UARTDivide1 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx1Divide,w ;1·
dec···· rs232Rx1Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx1Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx1Flag·········· ;1,23· then set flag
:rs232RxOut1
UART2
_bank rs232TxBank ;2 switch to serial register bank
sb rs232Tx2flag ;1
jmp rs232Receive2 ;1
decsz rs232Tx2Divide ;1 only execute the transmit routine
jmp rs232Receive2 ;1
mov w,#UARTDivide2 ;1 load UART2 baud rate (50MHz)
mov rs232Tx2Divide,w ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1
jmp rs232Receive2 ;1
:txbit stc···························· ;1 yes, ready stop bit
rr····· rs232Tx2High ;1· and shift to next bit
rr····· rs232Tx2Low ;1·
dec···· rs232Tx2Count ;1 decrement bit counter
snb rs232Tx2Low.6 ;1 output next bit
clrb rs232TxPin2 ;1·
sb rs232Tx2Low.6 ;1·
setb rs232TxPin2 ;1·
test··· rs232Tx2Count ;1 are we sending?
snz ;1·
clrb rs232Tx2Flag ;1,22
rs232Receive2
_bank rs232RxBank ;2
······· sb rs232RxPin2 ;1 get current rx bit
······· clc ;1·
······· snb rs232RxPin2 ;1·
······· stc ;1·
test··· rs232Rx2Count·········· ;1 currently receiving byte?
sz ;1·
jmp :rxbit················· ;1 if so, jump ahead
mov···· w,#9··················· ;1 in case start, ready 9 bits
sc ;1 skip ahead if not start bit
mov···· rs232Rx2Count,w ;1 it is, so renew bit count
mov···· w,#UARTStDelay2 ;1 ready 1.5 bit periods (50MHz)
mov···· rs232Rx2Divide,w ;1·
:rxbit········· decsz rs232Rx2Divide ;1 middle of next bit?
········· jmp :rs232RxOut2 ;1
mov w,#UARTDivide2 ;1 yes, ready 1 bit period (50MHz)
mov rs232Rx2Divide,w ;1·
dec···· rs232Rx2Count·········· ;1 last bit?
sz····························· ;1 if not
rr····· rs232Rx2Byte··········· ;1· then save bit
snz···························· ;1 if so,
setb··· rs232Rx2Flag·········· ;1,23· then set flag
:rs232RxOut2
UARTOut
;*********************************************************************************************
;===================================== PUT YOUR OWN VPs
HERE==================================
; Virtual Peripheral:
;
; Input variable(s):
; Output variable(s):
; Variable(s) affected:
; Flag(s) affected:
;*********************************************************************************************
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread2 ; Serviced at ISR rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread3····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread4····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread5····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread6····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread7····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread8····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread9····································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread10···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread11···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread12···································· ; Serviced at ISR
rate/16
;
jmp isrOut ; 7 cycles until mainline program resumes execution
;
isrThread13···································· ; Serviced at ISR
rate/16
·············································· ; This thread must
reload the isrMultiplex register
·············· _bank Multiplexbank
··············· mov isrMultiplex,#255 ;reload isrMultiplex so
isrThread1 will be run on the
··············································· ; next interrupt.
··············· jmp isrOut·········· ; 7 cycles until mainline program
resumes execution
; This thread must reload the isrMultiplex register
··············································· ; since it is the last
one to run in a rotation.
;
isrOut
;*********************************************************************************
; Set Interrupt Rate
;*********************************************************************************
isr_end
mov w,#intPeriod ;refresh RTCC on return
;(RTCC = 217, no. of instructions executed in the ISR)
retiw ;return from the interrupt
;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************
;*****************************************************************************************
; RESET VECTOR
;*****************************************************************************************
;*****************************************************************************************
;
Reset
Entry
;*****************************************************************************************
org RESETENTRY_ORG
resetEntry ; Program starts here on power-up
·· page _resetEntry
jmp _resetEntry
;*****************************************************************************************
;
UART
Subroutines
;*****************************************************************************************
org SUBROUTINES_ORG
;*****************************************************************************************
; Function : getbyte
; INPUTS : rs232RX1Flag,rs232Rx2Flag
; OUTPUTS : Received byte in rs232Rx1Byte or rs232Rx2Byte
; Get byte via serial port and echo it back to the serial port
;*****************************************************************************************
getbyte
getbyte1
_bank rs232RxBank ; switch to rs232 bank
sb rs232RX1Flag ; check if byte has been received by UART1
jmp getbyte2
clrb··· rs232Rx1Flag ; reset the receive flag
mov···· w,rs232Rx1Byte ; store byte (copy using W)
mov rs232Byte1,w
getbyte2 sb rs232Rx2Flag ; check if byte has been received by UART2
jmp [noparse]:o[/noparse]ut
clrb··· rs232Rx2Flag
mov w,rs232Rx2Byte
mov rs232Byte2,w
[noparse]:o[/noparse]ut retp
;****************************************************************************************
; Function : sendbyte
; INPUTS : rs232Tx1Flag set, rs232Tx1Byte - the byte to be sent via
UART1
; · rs232Tx2Flag set, rs232Tx2Byte- the byte to be sent via UART2
; OUTPUTS : Outputs The byte via RS-232 UART1/UART2
; Send byte via serial port
;
; Note: Before calling a sendbyte in Main, it should be ensured that
respective
; ····· flag of the UART rs232Tx1Flag/rs232Tx2Flag is CLEAR, and if
clear then a
; ····· byte can be sent, then the respective UART flag must be SET.
;****************************************************************************************
sendbyte···
sendbyte1
_bank··· rs232TxBank
test rs232Tx1Count
sz
jmp sendbyte2
sb rs232Tx1Flag
jmp sendbyte2
···· mov w,rs232Tx1Byte
not···· w ; ready bits (inverse logic)
mov···· rs232Tx1High,w········· ; store data byte
setb··· rs232Tx1Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx1Count,w
sendbyte2 test rs232Tx2Count
sz
jmp sendbyte1
sb rs232Tx2Flag
jmp [noparse]:o[/noparse]ut
mov w,rs232Tx2Byte
not w
mov···· rs232Tx2High,w········· ; store data byte
setb··· rs232Tx2Low.7·········· ; set up start bit
mov···· w,#10 ; 1 start + 8 data + 1 stop bit
mov···· rs232Tx2Count,w
[noparse]:o[/noparse]ut retp··························· ; leave and fix page bits
;*********************************************************************************
; Function : sendstring1
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART1
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring1 _bank rs232TxBank
mov···· localTemp1,w··········· ; store string address
:string test rs232Tx1Count
sz
jmp :string
setb rs232Tx1Flag ; SET flag for UART1
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx1Byte,w
call··· sendByte1············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx1Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;*********************************************************************************
; Function : sendstring2
; · Care should be taken that the srings are located within program
; · memory locations $300-$3ff as the area
; INPUTS : 'w', The address of a null-terminated string in program
memory
; OUTPUTS : outputs the string via RS-232 UART2
; Send string pointed to by address in W register
; Note: This routine is a locking routine in the sense that the
function returns
; to 'main' (the calling function) only after all the bytes of the
string
; are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring2 _bank rs232TxBank
mov···· localTemp1,w·········· ; store string address
:string test rs232Tx2Count
sz
jmp :string
setb rs232Tx2Flag ; SET flag for UART2
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
test··· w······················ ; are we at the last char?
snz···························· ; if not=0, skip ahead
jmp [noparse]:o[/noparse]ut··················· ; yes, leave & fix page bits
_bank rs232TxBank
mov rs232Tx2Byte,w
call··· sendByte2·············· ; not 0, so send character
_bank rs232TxBank
inc···· localTemp1············· ; point to next character
jmp···· :string············ ; loop until done
[noparse]:o[/noparse]ut clrb rs232Tx2Flag
mov w,#$1F ; reset the mode register
mov m,w
retp
;******************************************************************************************
org··· STRINGS_ORG···· ; This label defines where strings are kept in
program space.
;******************************************************************************************
;******************************************************************************************
;
String Data
;******************************************************************************************
;VP: RS232 Transmit
_welcome dw 191, 7, 131, 140, 7, 198, 7, 148, 7, 134, 8, 191, 139, 148,
0
_zero dw 167, 7, 128, 7, 149, 164, 0
_one dw 147, 14, 136, 8, 141, 0
_two dw 8, 191, 162, 0
_three dw 8, 190, 148, 8, 128, 0
_four dw 186, 7, 137, 153, 0
_five dw 186, 157, 166, 0
_six dw 8, 187, 129, 14, 194, 7, 187, 0
_seven dw 8, 187, 7, 131, 166, 131, 141, 0
_eight dw 154, 4, 191, 0
_nine dw 141, 14, 157, 141, 0
_point dw 7, 199, 7, 156, 15, 141, 15, 191, 0
_desee dw 8, 174, 128, 128, 5, 6, 8, 187, 128, 128, 0
_asee dw 8, 154, 1, 6, 8, 187, 26, 2, 128, 128, 0
_volts dw 166, 26, 1, 164, 26, 1, 146, 193, 0
_amps dw 133, 133, 140, 140, 199, 199, 8, 193, 0
_temper dw 191, 7, 131, 140, 7, 0, 198, 7, 148, 7, 134, 8, 191, 139,
148,0
_milli dw 140, 129, 145, 145, 128, 128, 0
_micro dw 140, 140, 157, 196, 196, 7, 148, 136, 8, 137, 0
_kilo dw 194, 7, 128, 14, 146, 137, 0
_mega dw 22, 88, 23, 5,0
_nano dw 14, 141, 7, 131, 0, 141, 141, 164,0
_hertz dw 183, 14, 148, 191, 193, 0
_negative dw 141, 130, 178, 133, 191, 129, 166, 0
_henries dw 184, 131, 131, 141, 141, 148, 148, 128, 15, 193, 0
_celcius dw 187, 130, 145, 187, 7, 128, 7, 134, 187, 0
_farad dw 186, 186, 132, 132, 14, 148, 132, 132, 15, 175, 187, 0
_cap dw 7, 195, 132, 132, 0, 199, 0, 132, 187, 129, 191, 132, 141,
187, 0
org PAGE3_ORG
jmp $
;******************************************************************************************
;
Main Program
; Program execution begins here on power-up or after a reset
;******************************************************************************************
org MAINPROGRAM_ORG
····
_resetEntry
;******************************************************************************************
;
Initialise all port configuration
;******************************************************************************************
_mode ST_W ;point MODE to write ST register
mov···· w,#RB_ST··········· ;Setup RB Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rb,w
mov···· w,#RC_ST··········· ;Setup RC Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_ST··········· ;Setup RD Schmitt Trigger, 0 = enabled,
1 = disabled
mov !rd,w
mov···· w,#RE_ST··········· ;Setup RE Schmitt Trigger, 0 = enabled,
1 = disabled
mov !re,w
ENDIF
_mode LVL_W ;point MODE to write LVL register
mov···· w,#RA_LVL··········· ;Setup RA CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !ra,w
mov···· w,#RB_LVL··········· ;Setup RB CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rb,w
mov···· w,#RC_LVL··········· ;Setup RC CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_LVL··········· ;Setup RD CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !rd,w
mov···· w,#RE_LVL··········· ;Setup RE CMOS or TTL levels, 1 = TTL,
0 = CMOS
mov !re,w
ENDIF
_mode PLP_W ;point MODE to write PLP register
mov···· w,#RA_PLP··········· ;Setup RA Weak Pull-up, 0 = enabled, 1
= disabled
mov !ra,w
mov···· w,#RB_PLP··········· ;Setup RB Weak Pull-up, 0 = enabled, 1
= disabled
mov !rb,w
mov···· w,#RC_PLP··········· ;Setup RC Weak Pull-up, 0 = enabled, 1
= disabled
mov !rc,w
IFDEF SX48_52
mov···· w,#RD_PLP··········· ;Setup RD Weak Pull-up, 0 = enabled, 1
= disabled
mov !rd,w
mov···· w,#RE_PLP··········· ;Setup RE Weak Pull-up, 0 = enabled, 1
= disabled
mov !re,w
ENDIF
_mode DDIR_W ;point MODE to write DDIR register
mov w,#RA_DDIR ;Setup RA Direction register, 0 = output, 1 = input
mov !ra,w
mov w,#RB_DDIR ;Setup RB Direction register, 0 = output, 1 = input
mov !rb,w
mov w,#RC_DDIR ;Setup RC Direction register, 0 = output, 1 = input
mov !rc,w
IFDEF SX48_52
mov w,#RD_DDIR ;Setup RD Direction register, 0 = output, 1 = input
mov !rd,w
mov w,#RE_DDIR ;Setup RE Direction register, 0 = output, 1 = input
mov !re,w
ENDIF
mov···· w,#RA_latch········· ;Initialize RA data latch
mov···· ra,w
mov···· w,#RB_latch········ ;Initialize RB data latch
mov···· rb,w
mov···· w,#RC_latch········· ;Initialize RC data latch
mov···· rc,w
IFDEF SX48_52
mov···· w,#RD_latch········ ;Initialize RD data latch
mov···· rd,w
mov···· w,#RE_latch········ ;Initialize RE data latch
mov···· re,w
ENDIF
;*********************************************************************************************************
;
Clear all Data RAM
locations
;**********************************************************************************************************
IFDEF SX48_52·· ;SX48/52 RAM clear routine
mov w,#$0a ;reset all ram starting at $0A
mov fsr,w
:zeroRam clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
_bank bank0 ;clear bank 0 registers
clr $10
clr $11
clr $12
clr $13
clr $14
clr $15
clr $16
clr $17
clr $18
clr $19
clr $1a
clr $1b
clr $1c
clr $1d
clr $1e
clr $1f
ELSE···· ;SX18/20/28 RAM clear routine
clr fsr ;reset all ram banks
:zeroRam sb fsr.4 ;are we on low half of bank?
setb fsr.3 ; To clear from 08 - Global Registers
clr ind ;clear using indirect addressing
incsz fsr ;repeat until done
jmp :zeroRam
ENDIF
;*********************************************************************************
; Initialize program/VP registers
;*********************************************************************************
_bank rs232TxBank ;select rs232 bank
mov w,#UARTDivide1 ;load rs232Tx1Divide with UART1 baud rate
mov rs232Tx1Divide,w
mov w,#UARTDivide2 ;load rs232Tx1Divide with UART2 baud rate
mov rs232Tx1Divide,w
;*********************************************************************************
; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler
;*********************************************************************************
RTCC_ON = %10000000 ;Enables RTCC at address $01 (RTW hi)
;*WREG at address $01 (RTW lo) by default
RTCC_ID = %01000000 ;Disables RTCC edge interrupt (RTE_IE hi)
;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT = %00100000 ;Sets RTCC increment on RTCC pin transition
(RTS hi)
;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE = %00010000 ;Sets RTCC to increment on falling edge (RTE_ES
hi)
;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON = %00000000 ;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF = %00001000 ;Assigns prescaler to WDT (PSA hi)
PS_000 = %00000000 ;RTCC = 1:2, WDT = 1:1
PS_001 = %00000001 ;RTCC = 1:4, WDT = 1:2
PS_010 = %00000010 ;RTCC = 1:8, WDT = 1:4
PS_011 = %00000011 ;RTCC = 1:16, WDT = 1:8
PS_100 = %00000100 ;RTCC = 1:32, WDT = 1:16
PS_101 = %00000101 ;RTCC = 1:64, WDT = 1:32
PS_110 = %00000110 ;RTCC = 1:128, WDT = 1:64
PS_111 = %00000111 ;RTCC = 1:256, WDT = 1:128
OPTIONSETUP equ RTCC_PS_OFF|PS_111 ; the default option setup for this
program.
mov w,#OPTIONSETUP ; setup option register for RTCC interrupts
enabled
mov !option,w ; and prescaler assigned to WDT.
jmp @mainLoop
;*****************************************************************************************
;
MAIN PROGRAM CODE
;*****************************************************************************************
mainLoop
IFDEF TEST1
mov w, #_welcome
setb rs232Tx1Flag
call @sendstring2
jmp mainloop1
mainloop1
call getbyte1 ; Get a Byte
_bank rs232RxBank
cje rs232Byte1,#'D',:desee
cje rs232Byte1,#'A',:asee
cje rs232Byte1,#'-',:negative
cje rs232Byte1,#'1',[noparse]:o[/noparse]ne
cje rs232Byte1,#'2',:two
cje rs232Byte1,#'3',:three
cje rs232Byte1,#'4',:four
cje rs232Byte1,#'5',:five
cje rs232Byte1,#'6',:six
cje rs232Byte1,#'7',:seven
cje rs232Byte1,#'8',:eight
cje rs232Byte1,#'9',:nine
cje rs232Byte1,#'.',[noparse]:p[/noparse]oint
cje rs232Byte1,#'0',:zero
cje rs232Byte1,#'n',:nano
cje rs232Byte1,#'u',:micro
cje rs232Byte1,#'m',:milli
cje rs232Byte1,#'M',:mega
cje rs232Byte1,#'k',:kilo
cje rs232Byte1,#'V',:volts
cje rs232Byte1,#'A',:amps
cje rs232Byte1,#'T',:temper
cje rs232Byte1,#'H',:hertz
cje rs232Byte1,#'C',:compare
cje rs232Byte1,#'F',:farad
:asee
mov w,#_asee
call @sendstring2
:desee
mov w,#_desee
call @sendstring2
:compare
call getbyte1
cje rs232Byte1,#'a',:cap
mov w,#_celcius
call @sendstring2
:cap
mov w,#_cap
call @sendstring2
:temper
mov w,#_temper
call @sendstring2
[noparse]:o[/noparse]ne
mov w,#_one
call @sendstring2
:two
mov w,#_two
call @sendstring2
:three
mov w,#_three
call @sendstring2
:four
mov w,#_four
call @sendstring2
:five
mov w,#_five
call @sendstring2
:six
mov w,#_six
call @sendstring2
:seven
mov w,#_seven
call @sendstring2
:eight
mov w,#_eight
call @sendstring2
:nine
mov w,#_nine
call @sendstring2
:zero
mov w,#_zero
call @sendstring2
[noparse]:p[/noparse]oint
mov w,#_point
call @sendstring2
:kilo
mov w,#_kilo
call @sendstring2
:nano
mov w,#_nano
call @sendstring2
:mega
mov w,#_mega
call @sendstring2
:milli
mov w,#_milli
call @sendstring2
:micro
mov w,#_micro
call @sendstring2
:amps
mov w,#_amps
call @sendstring2
:negative
mov w,#_negative
call @sendstring2
:farad
mov w,#_farad
call @sendstring2
:volts
mov w,#_volts
call @sendstring2
:hertz
mov w,#_hertz
call @sendstring2
:henries
mov w,#_henries
call @sendstring2
clr rs232Byte1
jmp mainloop1
ENDIF
jmp $ ; If program get stuck here, then you have not
; selected TEST1 or TEST2 at the beginning of
; the source code.
;*****************************************************************************************
END ;End of program code
;*****************************************************************************************
mov w,#STRINGS_ORG>>8 ; with indirect addressing
mov m,w
mov···· w,localTemp1··········· ; read next string character
iread·························· ; using the mode register
this is an IREAD sequence, which takes an address m:w and returns the 12bit value stored at that·address into m:w, the first line is storing the 4 most significant bits of the address STRINGS_ORG (a 12 bit address) into w, moved into m, the offset localTemp1 is placed for the lower 8 bits to form the complete address.