; *****************************************************************************************
; Copyright © [11/21/1999] Scenix Semiconductor, Inc. All rights reserved.
;
; Scenix Semiconductor, Inc. assumes no responsibility or liability for
; the use of this [product, application, software, any of these products].
; Scenix Semiconductor conveys no license, implicitly or otherwise, under
; any intellectual property rights.
; Information contained in this publication regarding (e.g.: application,
; implementation) and the like is intended through suggestion only and may
; be superseded by updates. Scenix Semiconductor makes no representation
; or warranties with respect to the accuracy or use of these information,
; or infringement of patents arising from such use or otherwise.
;*****************************************************************************************
;
; Filename: vpg_UART_1_04.src
;
; Authors: Chris Fogelklou
; Applications Engineer
; Scenix Semiconductor, Inc.
;
; ANAND.K.C
; Software Engineer
; Adamya Computing Technologies Pvt. Ltd.,
;
; Revision: 1.04
;
; Part: Put part datecode here.
; Freq: 50MHz
;
; Compiled using: SX-Key, SASM
;
; Date Written : Jan 15, 2000
;
; Last Revised : August 09, 2000
;
; Program Description:
;
; Virtual Peripherals Guidelines:
; Example source code, running at 50MHz, with just a transmit
; and receive UART. The code implements UART in software for baud rates of
; 1200,2400,4800,9600,19200,57600 bps depending on the rate selected,it can
; be selected to work at interrupt rate of 4.32us.
;
; Interface Pins:
;
; rs232RxPin equ ra.2 ;UART receive input
; rs232TxPin equ ra.3 ;UART transmit output
; rts_pin equ ra.0 ;UART 1 RTS input
; cts_pin equ ra.1 ;UART 1 CTS outpu
;
; Revision History:
;
; 1.0 Used the VP Guidelines multi-threaded example and inserted a UART
; for an example of code that actually works.
; 1.01 Removed all references to engineering samples of SX48/52
; 1.02 Fixed some assembly bugs created by rev 1.01
; 1.03
; July 01 1.04 As per the standard source code template & VP implementation
; guidelines.
; August 09 Modified as per review comments from Abdul Aleaf.
; Put rest of revision history here...
;*****************************************************************************************
;*****************************************************************************************
; Target SX
; Uncomment one of the following lines to choose the SX18AC,SX20AC,SX28AC,SX48BD, SX52BD.
;*****************************************************************************************
;SX18_20
;SX28AC
SX48_52
;*****************************************************************************************
; Assembler Used
; Uncomment the following line if using the Parallax SX-Key assembler. SASM assembler
; enabled by default.
;*****************************************************************************************
;SX_Key
;*****************************************************************************************
; Uncomment one of the following to run the uart vp at the required baud rate
;*****************************************************************************************
;baud1200 ;baud rate of 1.2 Kbps
;baud2400
;baud4800 ;baud rate of 4.8 Kbps
baud9600 ;baud rate of 9.6 kbps
;baud1920 ;baud rate of 19.2kbps
;baud5760 ;baud rate of 57.6kbps
;*****************************************************************************************
; Assembler directives
;
; High speed external osc, turbo mode, 8-level stack, and extended option reg.
; SX18/20/28 - 4 pages of program memory and 8 banks of RAM enabled by default.
; SX48/52 - 8 pages of program memory and 16 banks of RAM enabled by default.
;*****************************************************************************************
IFDEF SX_Key ;SX-Key Directives
IFDEF SX18_20 ;SX18AC or SX20AC device directives for SX-Key
device SX18L,oschs2,turbo,stackx_optionx
ENDIF
IFDEF SX28AC ;SX28AC device directives for SX-Key
device SX28L,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 SX18_20 ;SX18AC or SX20AC device directives for SASM
device SX18,oschs2,turbo,stackx,optionx
ENDIF
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 '1UART_VP' ;
reset resetEntry ; set reset vector
;*********************************************************************************
;--------------------------------------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 SX18/20/28AC 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
; (SX18/20/28) 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------------------------------------------
rs232RxFlag equ flags0.0 ;indicates the reception of a bit from the UART
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 bank
rs232Txhigh ds 1 ;hi byte to transmit
rs232Txlow ds 1 ;low byte to transmit
rs232Txcount ds 1 ;number of bits sent
rs232Txdivide ds 1 ;xmit timing (/16) counter
rs232Txflag ds 1
rs232RxBank = $
rs232Rxcount ds 1 ;number of bits received
rs232Rxdivide ds 1 ;receive timing counter
rs232Rxbyte ds 1 ;buffer for incoming byte
string ds 1 ;used by send_string to store the address in memory
rs232byte ds 1 ;used by serial routines
hex ds 1
MultiplexBank = $
isrMultiplex ds 1
;*********************************************************************************
; Bank 2
;*********************************************************************************
org bank2_org
bank2 = $
;*********************************************************************************
; 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 %00001000 ;SX18/20/28/48/52 port A latch init
RA_DDIR equ %11110111 ;SX18/20/28/48/52 port A DDIR value
RA_LVL equ %00000000 ;SX18/20/28/48/52 port A LVL value
RA_PLP equ %00001100 ;SX18/20/28/48/52 port A PLP value
RB_latch equ %00000000 ;SX18/20/28/48/52 port B latch init;intial value affter reset
RB_DDIR equ %11111111 ;SX18/20/28/48/52 port B DDIR value;0=Output,1=Input
RB_ST equ %11111111 ;SX18/20/28/48/52 port B ST value;0=Enable,1=Disable
RB_LVL equ %00000000 ;SX18/20/28/48/52 port B LVL value;0=CMOS,1=TTL
RB_PLP equ %00000000 ;SX18/20/28/48/52 port B PLP value;0=Enable,1=Disable
RC_latch equ %00000000 ;SX18/20/28/48/52 port C latch init;intial value affter reset
RC_DDIR equ %11111111 ;SX18/20/28/48/52 port C DDIR value;0=Output,1=Input
RC_ST equ %11111111 ;SX18/20/28/48/52 port C ST value;0=Enable,1=Disable
RC_LVL equ %00000000 ;SX18/20/28/48/52 port C LVL value;0=CMOS,1=TTL
RC_PLP equ %00000000 ;SX18/20/28/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 affter 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 affter 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----------------------------------------
;*****************************************************************************************
rs232RTSpin equ ra.0 ;UART RTS input
rs232CTSpin equ ra.1 ;UART CTS output
rs232Rxpin equ ra.2 ;UART receive input
rs232Txpin equ ra.3 ;UART transmit output
;*****************************************************************************************
;---------------------------------- Program constants-------------------------------------
;*****************************************************************************************
_enter equ 13 ; ASCII value for carridge return
_linefeed equ 10 ; ASCII value for a line feed
;*****************************************************************************************
; UART Constants values
;*****************************************************************************************
intPeriod = 217
UARTfs = 230400
Num = 4
IFDEF baud1200
UARTBaud = 1200
ENDIF
IFDEF baud2400
UARTBaud = 2400
ENDIF
IFDEF baud4800
UARTBaud = 4800
ENDIF
IFDEF baud9600
UARTBaud = 9600
ENDIF
IFDEF baud1920
UARTBaud = 19200
ENDIF
IFDEF baud5760
UARTBaud = 57600
ENDIF
UARTDivide = (UARTfs/(UARTBaud*Num))
UARTStDelay = UARTDivide +(UARTDivide/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
;*****************************************************************************************
; SX18AC/20AC/28AC Mode addresses
; *On SX18/20/28, 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
;---------------------------------------------VP: RS232 Transmit--------------------------
;*****************************************************************************************
; 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.
;
; RECEIVING: The rs232Rxflag is 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, if not needed, to reduce execution time and memory usage,
; as long as the initial "BANK serial" (common) instruction is kept.
; Input variable(s) : rs232Txlow (only high bit used), rs232Txhigh, rs232Txcount
; Output variable(s) : rs232Rxflag, rs232Rxbyte
; Variable(s) affected : rs232Txdivide, rs232Rxdivide, rs232Rxcount
; Flag(s) affected : rs232Rxflag
; Variable(s) affected : Txdivide
; Program cycles: 17 worst case
; Variable Length? Yes.
;*****************************************************************************************
rs232Transmit
_bank rs232TxBank ;2 switch to serial register bank
decsz rs232Txdivide ;1 only execute the transmit routine
jmp :rs232TxOut ;1
mov w,#UARTDivide ;1 load UART baud rate (50MHz)
mov rs232Txdivide,w ;1
test rs232Txcount ;1 are we sending?
snz ;1
jmp :rs232TxOut ;1
:txbit clc ;1 yes, ready stop bit
rr rs232Txhigh ;1 and shift to next bit
rr rs232Txlow ;1
dec rs232Txcount ;1 decrement bit counter
snb rs232Txlow.6 ;1 output next bit
clrb rs232TxPin ;1
sb rs232Txlow.6 ;1
setb rs232TxPin ;1,17
:rs232TxOut
;*****************************************************************************************
;----------------------------------------VP: RS232 Receive--------------------------------
; 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.
; RECEIVING: The rx_flag is 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.
; Output variable(s) : rx_flag, rx_byte
; Variable(s) affected : tx_divide, rx_divide, rx_count
; Flag(s) affected : rx_flag
; Program cycles: 23 worst case
; Variable Length? Yes.
;*****************************************************************************************
rs232Receive
_bank rs232RxBank ;2
sb rs232RxPin ;1 get current rx bit
clc ;1
snb rs232RxPin ;1
stc ;1
test rs232Rxcount ;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 rs232Rxcount,w ;1 it is, so renew bit count
mov w,#UARTStDelay ;1 ready 1.5 bit periods (50MHz)
mov rs232RxDivide,w ;1
:rxbit decsz rs232Rxdivide ;1 middle of next bit?
jmp :rs232RxOut ;1
mov w,#UARTDivide ;1 yes, ready 1 bit period (50MHz)
mov rs232Rxdivide,w ;1
dec rs232Rxcount ;1 last bit?
sz ;1 if not
rr rs232Rxbyte ;1 then save bit
snz ;1 if so,
setb rs232RxFlag ;1,23 then set flag
:rs232RxOut
;*****************************************************************************************
;===================================== 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
;*****************************************************************************************
isrend
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 : NONE
; OUTPUTS : Received byte in rs232Rxbyte
; Get byte via serial port and echo it back to the serial port
;*****************************************************************************************
getbyte jnb rs232RxFlag,$ ; wait till byte is received
clrb rs232RxFlag ; reset the receive flag
_bank rs232RxBank ; switch to rs232 bank
mov rs232byte,rs232Rxbyte ; store byte (copy using W)
retp
;*****************************************************************************************
; Function : sendbyte
; INPUTS : 'w' - the byte to be sent via RS-232
; OUTPUTS : Outputs The byte via RS-232
; Send byte via serial port
;*****************************************************************************************
sendbyte mov localTemp0,w
_bank rs232TxBank
:wait test rs232Txcount ; wait for not busy
sz
jmp :wait ;
not w ; ready bits (inverse logic)
mov rs232Txhigh,w ; store data byte
setb rs232Txlow.7 ; set up start bit
mov w,#10 ; 1 start + 8 data + 1 stop bit
mov rs232Txcount,w
retp ; leave and fix page bits
;*****************************************************************************************
; Function : sendstring
; 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
; Send string pointed to by address in W register
;*****************************************************************************************
sendstring _bank rs232TxBank
mov localTemp1,w ; store string address
:loop
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 :out ; yes, leave & fix page bits
call sendbyte ; not 0, so send character
_bank rs232TxBank
inc localTemp1 ; point to next character
jmp :loop ; loop until done
:out mov w,#$1F ; reset the mode register
mov m,w
retp
;*****************************************************************************************
; Function : uppercase
; INPUTS : byte - the byte to be converted
; OUTPUTS : byte - converted byte
; Convert byte to uppercase.
;*****************************************************************************************
uppercase mov w,#'a' ;if byte is lowercase, then skip ahead
mov w,rs232byte-w
sc
retp
mov w,#'a'-'A' ;change byte to uppercase
sub rs232byte,w
retp ;leave and fix page bits
;*****************************************************************************************
; Function : sendhex
; INPUTS : 'w' - the byte to be output
; OUTPUTS : Outputs the hex byte via RS-232
; Output a hex number
;*****************************************************************************************
sendhex mov localTemp1,w
swap wreg
and w,#$0f
call hextable
call sendbyte
mov w,localTemp1
and w,#$0f
call hextable
call sendbyte
retp
;*****************************************************************************************
; Function : gethex
; Inputs : None
; OUTPUTS : Received HEX value is in 'hex' register.
; This routine returns with an 8-bit value in the W and in the hex
; register. It accepts a hex number from the terminal screen and
; returns. Remember to write a prompt to the screen before calling get_hex
;*****************************************************************************************
gethex _bank rs232RxBank ;2
mov w,#_enterhex
call @sendstring
call :getvalidhex
mov w,rs232byte ; send the received (good) byte
call sendbyte
swap localTemp2 ; put the nibble in the upper nibble of
mov w,localTemp2
mov hex,w ; hex register
call :getvalidhex
mov w,rs232byte ; send the second received byte
call sendbyte
mov w,localTemp2
and w,#$0f
or w,hex
mov hex,w
retp
:getvalidhex
:gh1 clr localTemp2
jnb rs232Rxflag,$ ; get a byte from the terminal
clrb rs232Rxflag
mov rs232byte,rs232Rxbyte
call uppercase ; uppercase it.
:loop mov w,localTemp2 ; get the value at temp (index)
call hextable
xor w,rs232byte
snz ; compare it to the received byte
ret
inc localTemp2 ; if they are equal, we have the
jb localTemp2.4,:gh1 ; upper nybble. Continue if not.
jmp :loop
ret
hextable add pc,w
retw '0'
retw '1'
retw '2'
retw '3'
retw '4'
retw '5'
retw '6'
retw '7'
retw '8'
retw '9'
retw 'A'
retw 'B'
retw 'C'
retw 'D'
retw 'E'
retw 'F'
;*****************************************************************************************
org STRINGS_ORG ; This label defines where strings are kept in program space.
; all the following strings must be within the same half page of
; theprogram memory for sendstring to work,and they must be
; preceeded by this label.
;*****************************************************************************************
;*****************************************************************************************
;---------------------------------------String Data---------------------------------------
;*****************************************************************************************
;VP: RS232 Transmit
_hello dw 13,10,'Yup, The UART works!!!',0
_hitSpace dw 13,10,'Hit Space...',0
_enterhex dw 13,10,'Enter Hex Value',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,0,1 = TTL, 2..7 = 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?
;If so, don't touch regs 0-7
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,#UARTDivide ;load Txdivide with UART baud rate
mov rs232TXdivide,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 ;the default option setup for this program.
mov w,#OPTIONSETUP ;setup option register for RTCC interupts enabled
mov !option,w ;and no prescaler.
jmp @mainLoop
;*****************************************************************************************
;-------------------------------------- MAIN PROGRAM CODE --------------------------------
;*****************************************************************************************
mainLoop
mov w,#_hitSpace ; Send prompt to terminal at UART rate
call @sendstring
:loop
call @getbyte
cjne rs232Rxbyte,#' ',:loop ; just keep looping until user
; hits the space bar
mov w,#_hello ; When space bar hit, send out string.
call @sendstring
jmp :loop
;*****************************************************************************************
END ;End of program code
;*****************************************************************************************
file: /Techref/scenix/lib/io/osi2/serial/Vpg_UART_1_04.src, 50KB, , updated: 2000/10/11 10:55, local time: 2024/11/12 22:23,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/scenix/lib/io/osi2/serial/Vpg_UART_1_04.src"> scenix lib io osi2 serial Vpg_UART_1_04</A> |
Did you find what you needed?
|