please dont rip this site

Scenix Lib IO Dev Modem BELL_103_FULL_DUP_1_13.SRC

; ******************************************************************************
; Copyright © [01/25/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:	bell_103_tx.src
;
; Author:	Chris Fogelklou
;		Applications Engineer
;		Scenix Semiconductor Inc.
;
; Revision:	1.08
;
; Date:		April 16, 1999.
;
; Part:		SX28AC rev. 2.5
;
; Freq:		50Mhz
;
; Compiled using Parallax SX-Key software v1.0
;
; Version:	1.10
;
; Program Description:	This simple program encodes an outgoing bell103 signal.
;			This program only creates the answer frequencies, since it
;			cannot dial out to originate.
;
;			To use this program, connect the SX-DTMF-DEMO board to a phone
;			line and to a PC.  The communications settings are 300,N,8,1.
;			Now, from a remote BELL103 modem, simply dial the modem's number.
;			When you here the line ringing on the dialing modem, press a key
;			in the comm window of the SX-modem-board.  This should force the
;			modem board off-hook and cause it to send out an answer tone for
;			3 seconds.  Once the answer tone is sent, the modem board will
;			begin modulating the state of the RS-232 pin onto the carrier.
;			If the terminal program is set up correctly, you will be able to
;			receive the sent characters on the remote modem.
;
; Revision History:  	1.0  Tried for weeks to get FSK-receive to work.  Finally got it
;			working.
;			1.01 Tried to eliminate all unnecessary code...
;			1.04 Originate and answer modes both working.  AT command set added.
;			1.10 Changed the fsk receive code so it is simpler to understand and
;				uses less RAM.
;
;	INPUTS:
;	Received RS-232 characters on rs-232 rx_pin (ra.1)
;	OUTPUTS:
;	Received RS-232 characters on tx_pin (ra.2)
;	FSK output on PPM_pin
;	LED flashes (rb.0)
;
;	RESOURCES:
;       Program memory: TBD
;       Data memory:	TBD
;       I/O Count:	TBD
;
;******************************************************************************
; Device Directives
;******************************************************************************
SX28L_compiler
IFDEF SX28L_compiler
		device	SX28L,oscxt4,carryx		; 28-pin device, 4 pages, 8 banks of RAM
		device	turbo,stackx_optionx		; High speed oscillator, turbo mode,
							; option register extend, 8-level stack
ELSE
		device	pins28,pages4,banks8,carryx	; 28-pin device, 1 pages, 8 banks of RAM
		device	oschs,turbo,optionx,stackx	; High speed oscillator, turbo mode,
ENDIF							; option register extend, 8-level stack
		freq	50_000_000			; default run speed = 50MHz
		ID	'B103TX10'			; Version = 1.0

		reset	reset_entry			; JUMP to reset_entry label on reset


;******************************************************************************
; Watches (For Debug in SX_Key software V.1.0 +)
;******************************************************************************
watch	fsk_answering,1,ubin
watch	freq_acc_low,16,udec
watch	freq_count_low,16,udec
watch	sine_index,8,udec
watch	D_to_A_val,8,udec
watch	freq_acc_high,16,uhex
watch	freq_count_high,8,uhex
watch	freq_count_low,8,uhex
watch	freq_count_high2,8,uhex
watch	freq_count_low2,8,uhex
watch	byte,1,fstr
watch	byte,8,udec
watch	curr_sine,8,sdec
watch	sine_index,8,sdec
watch	D_to_A_val,8,udec
watch	PPM0_acc,8,udec
watch	timer_flag,1,ubin
watch	timer_l,16,uhex
watch	temp,8,uhex
watch	wreg,8,uhex
watch	fsk_last_trans,8,udec

watch	fsk_trans_avg_l,16,udec
watch	fsk_avg_count,8,udec
watch	fsk_trans_count,8,udec
watch	fsk_glitch_acc,8,udec
watch	fsk_high_byte,8,udec
watch	fsk_average_index,8,udec
watch	fsk_temp_trans,8,udec
watch	fsk_processing_required1,1,ubin
watch	fsk_processing_required2,1,ubin
watch	fsk_carrier_detected,1,ubin
watch	fsk_rb_past_state,8,ubin


;**************************************************************************
; Equates for common data comm frequencies
;**************************************************************************
f697_h		equ	$012	; DTMF Frequency
f697_l		equ	$09d

f770_h		equ	$014	; DTMF Frequency
f770_l		equ	$090

f852_h		equ	$016	; DTMF Frequency
f852_l		equ	$0c0

f941_h		equ	$019	; DTMF Frequency
f941_l		equ	$021

f1209_h		equ	$020	; DTMF Frequency
f1209_l		equ	$049

f1336_h		equ	$023	; DTMF Frequency
f1336_l		equ	$0ad

f1477_h		equ	$027	; DTMF Frequency
f1477_l		equ	$071

f1633_h		equ	$02b	; DTMF Frequency
f1633_l		equ	$09c
;******************************************************************************
; Equates for FSK generation
;******************************************************************************
f2225_h		equ	$03b
f2225_l		equ	$06b

f2025_h		equ	$036
f2025_l		equ	$014

f1070_h		equ	$01c
f1070_l		equ	$093

f1270_h		equ	$021
f1270_l		equ	$0ea

f2100_h		equ	$038	; 2100Hz Signifies LOW data in Bell202 Spec
f2100_l		equ	$015

;**************************************************************************
; Equates for certain baud rates: 
;**************************************************************************
;baud_bit	=       4                       ;for 19200 baud
;start_delay	=       16+8+1                  ; "    "     "
;int_period	=       163                     ; "    "     "
; *** 2400 baud (for slower baud rates, increase the RTCC prescaler)
baud_bit	=       7                       ;for 2400 baud
start_delay	=       128+64+1                ; "    "    "
fsk_start_delay	=	128+96+1
int_period	=       163                     ; "    "    "
;******************************************************************************
; Pin Definitions (These definitions are for SX DTMF DEMO boards)
;******************************************************************************
PPM_pin		equ	ra.0	; D/A output pin
rx_pin		equ	ra.1	; RS-232 reception pin
tx_pin		equ	ra.2	; RS-232 transmission pin
nothing		equ	ra.3	; N/C
ra_dir_mask	equ	%11111010	; sets up the I/O directions of port ra
ra_data_mask	equ	%11111111	; sets up the output levels of the output pins on ra

led_pin		equ	rb.0	; LED pin
rxa_pin		equ	rb.1	; FSK receive pin
cntrl_1		equ	rb.2	; drive cntrl_1 low to disable the output of the LPF
ring		equ	rb.3	; ring detection pin
hook		equ	rb.4	; drive hook low to go off-hook
cntrl_3		equ	rb.5	; drive cntrl_3 low to disable the output of the HPF
rts		equ	rb.6	; indicates to the SX that the PC wants to transmit data
cts		equ	rb.7	; indicates to the PC that the SX is ready to receive data
rb_dir_mask	equ	%01101110	; sets up the I/O directions of port rb
rb_data_mask	equ	%01011011	; sets up the output levels of the output pins on ra
LPF_mask	equ	%01001110	; when LPF is enabled, tristate cntrl 1 and put cntrl 3 low
HPF_mask	equ	%01101010	; when HPF is enabled, tristate cntrl 3 and put cntrl 1 low
LPF_HPF_mask	equ	%01101110	; when both filters are enabled, tristate cntrl 1 and cntrl 3


dtmf_in_pin	equ	rc.0
dtmf_fdbk_pin	equ	rc.1
AtoD_in_pin	equ	rc.2
AtoD_fdbk_pin	equ	rc.3
imp_450_pin	equ	rc.4
imp_600_pin	equ	rc.5
imp_750_pin	equ	rc.6                  
imp_900_pin	equ	rc.7
rc_dir_mask	equ	%11010101	; sets up the I/O directions of port rc
rc_data_mask	equ	%00001111	; sets up the output levels of the output pins on ra
;******************************************************************************
; Global Variables
;******************************************************************************
		org	$8		; Global registers

	flags	ds	1
		dtmf_gen_en	equ	flags.0	; Signifies whether or not DTMF output is enabled
		sine_gen_en	equ	flags.1
		timer_flag	equ	flags.2
		fsk_tx_en	equ	flags.3
		fsk_rx_en	equ	flags.4 ; Enables the FSK receiver.
		rx_flag		equ	flags.5
		fsk_rx_flag	equ	flags.6
	temp		ds	1
	task_switcher	ds	1
	ascii_index	ds	1
	command_index	ds	1
;******************************************************************************
; Bank 0 Variables
;******************************************************************************
		org	$10

sine_gen_bank		=	$
	freq_acc_low		ds	1	; 16-bit accumulator which decides when to increment the sine wave
	freq_acc_high		ds	1	; 
	freq_count_low		ds	1	; 16-bit counter which decides which frequency for the sine wave
	freq_count_high		ds	1	; freq_count = Frequency * 6.83671552
	sine_index		ds	1
	sine_index2		ds	1	; The velocity of the sin wave
	freq_count_low2		ds	1	; 16-bit counter which decides which frequency for the sine wave
	freq_count_high2	ds	1	; freq_count = Frequency * 6.83671552
	freq_acc_high2		ds	1	; 
	freq_acc_low2		ds	1	; 16-bit accumulator which decides when to increment the sine wave
	curr_sine		ds	1	; The current value of the imitation sin wave
	curr_sine2		ds	1	; The current value of the imitation sin wave
	sine2_temp		ds	1	; This register is used to do a temporary shift/add register

PPM_bank		=	$

PPM0_acc		ds	1		; PPM accumulator
D_to_A_val			ds	1		; current PPM output

;******************************************************************************
; Bank 1 Variables
;******************************************************************************
		org	$30
timers			=	$
	timer_l		ds	1
	timer_h		ds	1
	timer_hh	ds	1
serial		=       $                       ;UART bank

tx_high		ds      1                       ;hi byte to transmit
tx_low		ds      1                       ;low byte to transmit
tx_count	ds      1                       ;number of bits sent
tx_divide	ds      1                       ;xmit timing (/16) counter
rx_count	ds      1                       ;number of bits received
rx_divide	ds      1                       ;receive timing counter
rx_byte		ds      1                       ;buffer for incoming byte
rx_count2	ds      1                       ;number of bits received
rx_divide2	ds      1                       ;receive timing counter
rx_byte2	ds      1                       ;buffer for incoming byte
string		ds	1
byte		ds	1
plus_count	ds	1

;******************************************************************************
;	Bank 2 Variables
;******************************************************************************
		org     $50                     ;bank3 variables
fsk_receive_bank	=	$
fsk_transmit_bank	=	$

	fsk_last_trans		ds	1
	fsk_trans_avg_l		ds	1
	fsk_trans_avg_h		ds	1
	fsk_avg_count		ds	1
	fsk_trans_count		ds	1		; This register counts the number of counts 
							; between transitions at the pin
	fsk_rb_past_state 	ds	1		; This register keeps track of the previous 
							; state of port RB, to watch for transitions
	fsk_glitch_acc		ds	1
	fsk_average		ds	1
	fsk_high_byte		ds	1
	fsk_average_index	ds	1
	fsk_temp_trans		ds	1
	fsk_no_carrier_count	ds	1

	fsk_flags		ds	1
	fsk_answering		equ	fsk_flags.0
	fsk_tx_bit		equ	fsk_flags.1
	fsk_rx_bit		equ	fsk_flags.2
	fsk_processing_required1 equ	fsk_flags.3
	fsk_processing_required2 equ	fsk_flags.4
	fsk_rx_bit_last		equ	fsk_flags.5
	fsk_carrier_detected	equ	fsk_flags.6
	fsk_answer_tone		equ	fsk_flags.7
;*************************************************************
; Bank 4, 5, 6, 7 (for ascii buffer, but can be reused.)
;*************************************************************
		org	$90
	ascii_buffer		=	$
		org	$b0
	ascii_buffer2		=	$
		org	$d0
	ascii_buffer3		=	$
		org	$f0
	ascii_buffer4		=	$

;************************ Beginning of program space ***************************
;******************************************************************************
; Interrupt
		org	$0			; The interrupt Service routine starts at location zero.
; 
; With a retiw value of -163 and an oscillator frequency of 50MHz, this
; code runs every 3.26us.
;******************************************************************************
PPM_output
		bank	PPM_bank		; Update the PPM pin
		clc
		add	PPM0_acc,D_to_A_val
		snc
		setb	PPM_pin
		sc
		clrb	PPM_pin
;******************************************************************************
FSK_output
		jnb	dtmf_gen_en,:dtmf_disabled
		call	@sine_generator1
		jmp	:task_switcher
:dtmf_disabled
		snb	sine_gen_en		; Output the frequencies set by the freq_count registers
		call	@sine_generator2
		snb	fsk_rx_en
		call	@fsk_receive
:task_switcher
		inc	task_switcher
		mov	w,task_switcher
		and	w,#$07
		clc
		jmp	pc+w
		jmp	:fsk_process_1	;0
		jmp	:fsk_process_2 	;1
		jmp	:fsk_process_3	;2
		jmp	:fsk_transmit	;3

		jmp	:fsk_get_carrier;4
		jmp	do_timers	;5
		jmp	:transmit	;6
		jmp	:receive	;7


:fsk_process_1
		call	@FSK_RECEIVE_PROCESSING1
		jmp	do_timers
:fsk_process_2
		call	@FSK_RECEIVE_PROCESSING2
		jmp	do_timers
:fsk_process_3
		call	@FSK_RECEIVE_PROCESSING3
		jmp	do_timers
:fsk_transmit
		snb	fsk_tx_en
		call	@TRANSMIT_FSK		; into its corresponding frequencies
		jmp	do_timers
:fsk_get_carrier
		call	@FSK_GET_CARRIER
		jmp	do_timers
		
;**************************************************************************
:transmit
; This is an asynchronous RS-232 transmitter
; INPUTS:
;	tx_divide.baud_bit  -	Transmitter only executes when this bit is = 1
;	tx_high		    -	Part of the data to be transmitted
;	tx_low		    -	Some more of the data to be transmitted
;	tx_count	    -	Counter which counts the number of bits transmitted.
; OUTPUTS:
;	tx_pin		    -	Sets/Clears this pin to accomplish the transmission.
;**************************************************************************
		bank	serial
		clrb    tx_divide.baud_bit      ;clear xmit timing count flag
		inc     tx_divide               ;only execute the transmit routine
		STZ                             ;set zero flag for test
		SNB     tx_divide.baud_bit      ; every 2^baud_bit interrupt
		test    tx_count                ;are we sending?
		JZ      do_timers	        ;if not, go to :receive
		clc                             ;yes, ready stop bit
		rr      tx_high                 ; and shift to next bit
		rr      tx_low                  ;
		dec     tx_count                ;decrement bit counter
		movb    tx_pin,/tx_low.6        ;output next bit
		jmp	do_timers
;**************************************************************************
:receive
; This is an asynchronous receiver for RS-232 reception
; INPUTS:
;	rx_pin		   -	Pin which RS-232 is received on.
; OUTPUTS:
;	rx_byte		   -	The byte received
;	rx_flag		   -	Set when a byte is received.
;**************************************************************************
		bank	serial
		movb    c,rx_pin                ;get current rx bit
		test    rx_count                ;currently receiving byte?
		jnz     :rxbit                  ;if so, jump ahead
		mov     w,#9                    ;in case start, ready 9 bits
		sc                              ;skip ahead if not start bit
		mov     rx_count,w              ;it is, so renew bit count
		mov     rx_divide,#start_delay  ;ready 1.5 bit periods
:rxbit		djnz    rx_divide,:rxdone       ;middle of next bit?
		setb    rx_divide.baud_bit      ;yes, ready 1 bit period
		dec     rx_count                ;last bit?
		sz                              ;if not
		rr      rx_byte                 ;  then save bit
		snz                             ;if so
		setb    rx_flag                 ;  then set flag
:rxdone

;**************************************************************************
do_timers
		bank	timers			; Update the timers
		inc	timer_l
		snz
		inc	timer_h
		snz
		setb	timer_flag
		snz
		inc	timer_hh
		setb	led_pin
		sb	timer_h.6
		clrb	led_pin
;******************************************************************************
:ISR_DONE
; This is the end of the interrupt service routine.  Now load 163 into w and
; perform a retiw to interrupt 163 cycles from the start of this one.  
; (3.26us@50MHz)
;******************************************************************************
		mov	w,#-163		;1	; interrupt 163 cycles after this interrupt
		retiw			;3	; return from the interrupt
;******************************************************************************
; End of the Interrupt Service Routine
;******************************************************************************

;**************************************************************************
time_n_ticks
; This subroutine times 'w' ticks, and returns with a '1' in w when 
; the specified time has timed out.  Each tick is 213.647 ms.
; This subroutine uses the TEMP register
; INPUT		w	-	# of milliseconds to delay for.
; OUTPUT	Returns after n milliseconds.
;**************************************************************************
	bank	timers
	test	wreg
	jz	:check_time
	clc
	add	w,timer_hh
	mov	temp,w
	retw	0
:check_time
	mov	w,temp
	xor	w,timer_hh
	sz	
	retw	0
	retw	1
;******************************************************************************
reset_entry
; Program Starts Here on Power Up
;******************************************************************************

		call	@init

		mov	!option,#%00011111	; enable wreg and rtcc interrupt
		mov	w,#_hello
		call	@send_string

main_2
_send_prompt	mov	w,#_CR
		call	@send_string
		mov	w,#_prompt			; send prompt
		call	@send_string

_cmd_loop
		jnb	rx_flag,$
		clrb	rx_flag
		bank	serial
		mov	byte,rx_byte
		call	@uppercase			; convert it to uppercase
		stc
		cje	byte,#$20,_cmd_loop		; if it equals a space, ignore it.
		stc
		cje	byte,#$0d,:enter		; if it equals a carriage return, parse the string.
		mov	w,byte				; if it does not resemble the above characters, echo it.
		call	@send_byte
		stc
		cje	byte,#$08,:backspace		; if it equals a backspace, delete one character in the buffer.
		call	@buffer_push			; otherwise, store it
		jmp	_cmd_loop			; and come back for more.
:backspace
		call	@buffer_backspace
		jmp	_cmd_loop

:enter							; If the user presses enter, then parse the string.


;**************************************************************************
; String parser (Checks to see if buffer = any commands)
; -Checks contents of ascii buffer against any commands stored in ROM
; -If a command = the contents of the ascii buffer, a routine will be called
; -Each routine MUST perform a retw 0 on exit, or parse_string will not 
;  know that a routine has run and it should exit back to command mode.
; -Exits back to command mode when it detects a zero after the table look-up.
; -Outputs 'OK' if no commands are matched.
;**************************************************************************
parse_string
		clr	ascii_index			; Clear the index into the ascii buffer
		clr	command_index			; And the index into the commands
		
:loop		call	@buffer_get			; Get a vale from the buffer at ascii_index
		call	command_table			; Get a character from one of the commands
		test	wreg				; If the return value is 0, then this matched
		jz	:nothing			; the command and ran a routine.  Exit.
		bank	serial				
		xor	w,byte				; compare the command's character with the 
		jnz	:not_equal			; buffer's character.
		call	@inc_ascii_index		; Increment the index into the buffer.
		jmp	:loop
:not_equal
		inc	command_index			; If the buffer did not equal the command,
		clr	ascii_index			; start from the beginning of a new command 
		stc
		cjne	command_index,#6,:loop		; and the buffer.  (This number = # of commands)
:nothing	mov	w,#_CR
		call	@send_string
		mov	w,#_OK				; If we have checked all 4 commands, then this
		call	@send_string			; did not equal any so send an 'OK' message.
:done
		bank	ascii_buffer
		clr	ascii_index
		clr	ascii_buffer
		jmp	_send_prompt

;**************************************************************************
command_table
		mov	w,command_index
		clc
		add	pc,w
		jmp	command_1
		jmp	command_2
		jmp	command_3
		jmp	command_4
		jmp	command_5
		jmp	command_6
;**************************************************************************
command_1					; Dial command
		mov	w,ascii_index
		add	PC,w
		retw	'A'
		retw	'T'
		retw	'D'
		retw	'T'
		jmp	DIAL_MODE
;**************************************************************************
command_2					; Hang up command
		mov	w,ascii_index
		add	PC,w
		retw	'A'
		retw	'T'
		retw	'H'
		jmp	HANG_UP
;**************************************************************************
command_3					; Initialize
		mov	w,ascii_index
		add	PC,w
		retw	'A'
		retw	'T'
		retw	'Z'
		jmp	INITIALIZE
;**************************************************************************
command_4					; Answer/ Auto answer
		mov	w,ascii_index
		add	PC,w
		retw	'A'
		retw	'T'
		retw	'A'
		jmp	AUTO_ANSWER
;**************************************************************************
command_5					; Data mode
		mov	w,ascii_index
		add	PC,w
		retw	'A'
		retw	'T'
		retw	'O'
		jmp	FSK_IO
;**************************************************************************
command_6					; Help
		mov	w,ascii_index
		add	PC,w
		retw	'?'
		jmp	HELP
;**************************************************************************
; END of String parser (Checks to see if buffer = any commands)
;**************************************************************************
HANG_UP
		setb	hook
		retw	0
INITIALIZE
		call	@init
		clr	flags
		retw	0
AUTO_ANSWER
		jmp	Answer
		retw	0
HELP		retw	0
				
	;**************************************************************************
	; Dial Mode:
	; -Dials contents of ascii buffer, starting from location pointed
	;  to by ascii_index.
	; -Responds to these commands:
	; 	0-9, *, #	- Dials the specified number
	;	,		- Pause for 2 seconds
	; -Jumps to data mode after dialing.
	;**************************************************************************
DIAL_MODE
		mov	w,#_CR
		call	@send_string
		mov	w,#_DIALING			; send Dialing
		call	@send_string
		clrb	hook
		
		mov	w,#255
		call	@delay_10n_ms
		bank	serial

:dial_loop	call	@buffer_get			; wait for an input character
		call	@uppercase			; convert it to uppercase
		mov	w,byte
		snz
		jmp	:originate_mode
		call	@send_byte
		cje	byte,#',',:pause		; if the character = ',', pause for 2s
		call	@digit_2_index			; convert the ascii digit to an 
							; index value
		call	@load_frequencies		; load the frequency registers
		call	@dial_it			; dial the number for 60ms and return.
:inc		call	@inc_ascii_index		; increment the index into the table
		jmp	:dial_loop
:pause
		mov	w,#201				; delay 2s
		call	@delay_10n_ms
		jmp	:inc


:originate_mode
	;******************************************************************
	; Go off-hook
	;******************************************************************
		mov	m,#$0f
		mov	!rb,#HPF_mask	; Enable HPF and disable LPF
		clrb	cntrl_1
		clr	flags
		bank	fsk_transmit_bank
		clrb	fsk_answering
		setb	fsk_rx_en
		setb	fsk_tx_bit
		setb	sine_gen_en
		setb	fsk_tx_en
		mov	w,#140				; wait 30 seconds for answer_tone
		call	time_n_ticks
:loop
;		clr	w
;		call	time_n_ticks
;		test	wreg
;		jnz	no_carrier
;		bank	fsk_receive_bank
;		jnb	fsk_answer_tone,:loop
		jmp	FSK_IO

Answer
		clrb	hook				; Go off-hook
		mov	m,#$0f
		mov	!rb,#LPF_mask	; Enable LPF and disable HPF
		clrb	cntrl_3
		call	@answer_tone			; Send out the answer tone for 3 seconds
		bank	fsk_transmit_bank		; Clear all the flags
		clr	flags
		setb	fsk_answering			; enable answering frequencies
		setb	fsk_tx_bit			; Set the tx_bit to output a high frequency
		setb	fsk_tx_en			; enable FSK transmit
		setb	sine_gen_en			; enable sine generation
		mov	w,#255
		call	@delay_10n_ms
		mov	w,#255
		call	@delay_10n_ms
		bank	fsk_receive_bank		; enable FSK receive
		setb	fsk_rx_en

FSK_IO

		mov	w,#47
		call	time_n_ticks
:loop
		clr	w
		call	time_n_ticks
		test	wreg
;		jnz	no_carrier
		bank	fsk_receive_bank
;		jnb	fsk_carrier_detected,:loop

		mov	w,#_DATA_MODE
		call	@send_string
		mov	w,#_prompt
		call	@send_string
		clr	plus_count
:loop2
		bank	fsk_receive_bank
;		jnb	fsk_carrier_detected,no_carrier
		movb	fsk_tx_bit,rx_pin	; move the rs-232 pin to the fsk_tx_bit
		movb	tx_pin,fsk_rx_bit	; and move the fsk_rx_bit to the rs-232 pin
		jb	rx_flag,:check_for_plus
		jmp	:loop2			; jump here forever (ISR does all the work)
:check_for_plus
		bank	serial
		clrb	rx_flag
		inc	plus_count
		mov	w,#'+'
		xor	w,rx_byte
		sz
		clr	plus_count
		mov	w,#3
		xor	w,plus_count
		snz
		retw	0
		jmp	:loop2

no_carrier
		setb	tx_pin
		mov	w,#255
		call	@delay_10n_ms
		mov	w,#_no_carrier
		call	@send_string
		bank	serial
:loop		test	tx_count
		jz	INITIALIZE
		jmp	:loop
		


org	$200

;******************************************************************************
FSK_RECEIVE
;**************************************************************************
		bank	fsk_receive_bank	; switch to fsk_receive_bank of RAM

		inc	fsk_trans_count		; Increment the transition count
		snz
		dec	fsk_trans_count		; If the result is zero, keep fsk_trans_count in range
		clc
		mov	w,fsk_rb_past_state	; Check for a transition
		xor	w,rb
		and	w,#%00000010
		snz
		retp				; return if there has been no transition
		xor	fsk_rb_past_state,w	; save the new value of the FSK_pin
		jb	fsk_answering,:dont_double
		sb	fsk_rb_past_state.1
		retp
:dont_double
		clc
		mov	w,#-30
		add	w,fsk_trans_count
		jnc	:glitch
		mov	fsk_temp_trans,fsk_trans_count
		clc
		add	fsk_trans_avg_l,w
		snc
		inc	fsk_trans_avg_h
		inc	fsk_avg_count
		clr	fsk_trans_count
		setb	fsk_processing_required1
		retp

:glitch		; Save any glitches in the glitch accumulator, to be added to 
		; the transition count before processing
		clc
		add	fsk_glitch_acc,fsk_trans_count
		retp



;**************************************************************************
FSK_RECEIVE_PROCESSING1	; This code is not very speed critical and can
			; run every so often in the ISR.
;**************************************************************************

		bank	fsk_receive_bank
		sb	fsk_processing_required1
		retp
		clrb	fsk_processing_required1
		setb	fsk_processing_required2
		retp


;**************************************************************************
FSK_RECEIVE_PROCESSING2	; This code is not very speed critical and can
			; run every so often in the ISR.
;**************************************************************************
	;******************************************************************
	; If no processing is required, exit
	;******************************************************************
		bank	fsk_receive_bank		;1
		sb	fsk_processing_required2	;1
		retp					;1
		clrb	fsk_processing_required2	;1

	;******************************************************************
	; Add the last transition time to this one, and divide by two.
	; and also add the glitch accumulator.
	;******************************************************************

		clc
		rr	fsk_glitch_acc
		clc
		mov	w,fsk_last_trans
		add	w,fsk_temp_trans
		rr	wreg
		clc
		add	w,fsk_glitch_acc
		clr	fsk_glitch_acc
		
	;******************************************************************
	; Now compare the result to 130 for answer mode or to 145 for
	; originate mode.  Anything above this threshold is a "high" bit,
	; and anything below this threshold is a "low" bit.
	;******************************************************************
		mov	fsk_last_trans,w		;1
		mov	w,#-130				;1
		sb	fsk_answering			;1
		mov	w,#-145				;1
		clc					;1
		add	w,fsk_last_trans		;1
		setb	fsk_rx_bit			;1
		snc					;1
		clrb	fsk_rx_bit			;1;50
							;3;53
		mov	fsk_last_trans,fsk_temp_trans
		retp
;**************************************************************************
FSK_RECEIVE_PROCESSING3
;**************************************************************************

		retp
		bank	fsk_receive_bank
		sb	fsk_rx_bit
		jmp	:rx_bit_low
:rx_bit_high
		snb	fsk_rx_bit_last
		retp
		setb	fsk_rx_bit_last
		mov	w,#121
		sb	fsk_answering
		mov	w,#138
		jmp	:hysterises
:rx_bit_low
		sb	fsk_rx_bit_last
		retp
		clrb	fsk_rx_bit_last
		mov	w,#144
		sb	fsk_answering
		mov	w,#152
:hysterises
		mov	fsk_last_trans,w
		retp
;**************************************************************************
FSK_GET_CARRIER
;**************************************************************************
		bank	fsk_receive_bank
		mov	w,fsk_avg_count
		sz
		retp
		inc	fsk_avg_count
		clrb	fsk_answer_tone
		clrb	fsk_carrier_detected
		jb	fsk_answering,:low_freqs
		mov	w,#-135
		clc
		add	w,fsk_trans_avg_h
		jnc	:get_answer_tone; If the average transition
					; time is less than 138, error...
		mov	w,#-152
		clc
		add	w,fsk_trans_avg_h
		sc
		setb	fsk_carrier_detected
:get_answer_tone
		mov	w,#-142
		clc
		add	w,fsk_trans_avg_h
		jnc	:no_answer_tone
		mov	w,#-148
		clc
		add	w,fsk_trans_avg_h
		sc
		setb	fsk_answer_tone
:no_answer_tone
		clr	fsk_trans_avg_h
		clr	fsk_trans_avg_l
		retp
:low_freqs
		mov	w,#-118
		clc
		add	w,fsk_trans_avg_h
		jnc	:no_carrier	; If the average transition
					; time is less than 138, error...
		mov	w,#-145
		clc
		add	w,fsk_trans_avg_h
		sc	
		setb	fsk_carrier_detected
:no_carrier	clr	fsk_trans_avg_h
		clr	fsk_trans_avg_l
		retp
		

		
		
		
;**************************************************************************
TRANSMIT_FSK
;**************************************************************************
		bank	fsk_transmit_bank
		jb	fsk_answering,transmit_answer_tones
transmit_originate_tones
		jnb	fsk_tx_bit,:low_freq
:high_freq
		bank	sine_gen_bank
		mov	freq_count_high2,#f1270_h
		mov	freq_count_low2,#f1270_l
		retp
:low_freq	
		bank	sine_gen_bank
		mov	freq_count_high2,#f1070_h
		mov	freq_count_low2,#f1070_l
		retp
transmit_answer_tones
		jnb	fsk_tx_bit,:low_freq
:high_freq
		bank	sine_gen_bank
		mov	freq_count_high2,#f2225_h
		mov	freq_count_low2,#f2225_l
		retp
:low_freq	
		bank	sine_gen_bank
		mov	freq_count_high2,#f2025_h
		mov	freq_count_low2,#f2025_l
		retp
;**************************************************************************
answer_tone
;**************************************************************************
		bank	sine_gen_bank		; send out the answer tone for 3 seconds
		clr	curr_sine
		mov	freq_count_high2,#f2100_h 
		mov	freq_count_low2,#f2100_l
		setb	sine_gen_en		; enable the FSK transmitter
		mov	w,#255
		call	@delay_10n_ms
		mov	w,#45
		call	@delay_10n_ms
		retp
;**************************************************************************
org	$300
;**************************************************************************
; String data (for RS-232 output) and tables
;**************************************************************************
_hello          dw      13,10,'SX Modem V 4.0',13,10,0
_instructions	dw	'- ? For Help',0
_DIALING	dw	'DIAL ',0
_ANSWERING	dw	'ANSWERING ',0
_AUTO_ANSWER	dw	'AUTO ANSWER ',13,10,0
_RING		dw	'RING',13,10,0
_PROMPT		dw	13,10,'>',0
_HANGING_UP	dw	'HANG UP ',13,10,0
_ATDT		dw	13,10,'ATDT=',0
_ATA		dw	'ATA =',0
_ATH		dw	'ATH =',0
_ATZ		dw	'ATZ =',0
_ATO		dw	'ATO =',0
_plus		dw	13,10,'+++ =',0
_OK		dw	'OK',13,10,0
_CR		dw	13,10,0
_COMMAND_MODE	dw	'COMMAND MODE',13,10,0
_DATA_MODE	dw	13,10,'CONNECT 300',0
_no_carrier	dw	13,10,'NO CARRIER',0
_INIT		dw	'INIT',0

org	$400	; Miscellaneous subroutines
;**************************************************************************
buffer_push
; This subroutine pushes the contents of byte onto the 32-byte ascii buffer. 
;**************************************************************************
	bank	serial			; Move the byte into the buffer
	mov	temp,byte
	mov	fsr,#ascii_buffer
	clc
	add	fsr,ascii_index
	mov	indf,temp
					; Increment index and keep it in range
	call	@inc_ascii_index
	mov	fsr,#ascii_buffer	; Null terminate the buffer.
	clc
	add	fsr,ascii_index
	clr	indf
	bank	serial
	retp
;**************************************************************************
;**************************************************************************
buffer_backspace
; This subroutine deletes one value of the buffer and decrements the index 
;**************************************************************************
	dec	ascii_index
	and	ascii_index,#%01101111

	mov	fsr,#ascii_buffer
	clc
	add	fsr,ascii_index
	clr	indf
	bank	serial
	retp
;**************************************************************************
inc_ascii_index
; This subroutine increments the index into the buffer
;**************************************************************************
	mov	w,ascii_index
	and	w,#%00001111
	xor	w,#%00001111
	jnz	:not_on_verge
	inc	ascii_index
	mov	w,#16
	clc
	add	w,ascii_index
	and	w,#$7f
	mov	ascii_index,w
	retp
:not_on_verge
	inc	ascii_index
	retp
;**************************************************************************
buffer_get
; This subroutine retrieves the buffered value at index
;**************************************************************************
	mov	fsr,#ascii_buffer
	clc
	add	fsr,ascii_index
	mov	w,indf
	bank	serial
	mov	byte,w
	
	retp
;**************************************************************************
delay_10n_ms
; This subroutine delays 'w'*10 milliseconds. 
; This subroutine uses the TEMP register
; INPUT		w	-	# of milliseconds to delay for.
; OUTPUT	Returns after 10 * n milliseconds.
;**************************************************************************
	mov	temp,w
	bank	timers
:loop	clrb	timer_flag	; This loop delays for 10ms
	mov	timer_h,#$0f4
	mov	timer_l,#$004
	jnb	timer_flag,$
	dec	temp		; do it w-1 times.
	jnz	:loop
	clrb	timer_flag
	retp
;**************************************************************************
delay_n_ms
; This subroutine delays 'w' milliseconds. 
; This subroutine uses the TEMP register
; INPUT		w	-	# of milliseconds to delay for.
; OUTPUT	Returns after n milliseconds.
;**************************************************************************
	mov	temp,w
	bank	timers
:loop	clrb	timer_flag	; This loop delays for 1ms
	mov	timer_h,#$0fe
	mov	timer_l,#$0cd
	jnb	timer_flag,$
	dec	temp		; do it w-1 times.
	jnz	:loop
	clrb	timer_flag
	retp
;**************************************************************************
zero_ram
; Subroutine - Zero all ram.
; INPUTS:	None
; OUTPUTS:	All ram locations (except special function registers) are = 0
;**************************************************************************
		CLR	FSR
:loop	    	SB      FSR.4                   ;are we on low half of bank?
		SETB    FSR.3                   ;If so, don't touch regs 0-7
		CLR     IND                     ;clear using indirect addressing
		IJNZ    FSR,:loop	        ;repeat until done
		retp
;**************************************************************************
init
;**************************************************************************
		mov	m,#$0d
		mov	!ra,#$00		; initialize all ports to CMOS levels
		mov	!rb,#$00
		mov	!rc,#$00
		mov	m,#$0f			; initialize the ports
		mov	!ra,#ra_dir_mask
		mov	ra,#ra_data_mask
		mov	!rb,#rb_dir_mask
		mov	rb,#rb_data_mask
		mov	!rc,#rc_dir_mask
		mov	rc,#rc_data_mask
		setb	hook			; go on hook.
		setb	led_pin			; turn on LED
		clr	flags			; Clear all flags
		call	zero_ram
		retp
;**************************************************************************
; Subroutine - Get byte via serial port and echo it back to the serial port
; INPUTS:
;	-NONE
; OUTPUTS:
;	-received byte in rx_byte
;**************************************************************************
get_byte     	jnb     rx_flag,$		;wait till byte is received
		clrb    rx_flag		;reset the receive flag
		bank	serial
		mov     byte,rx_byte		;store byte (copy using W)
						; & fall through to echo char back
;**************************************************************************
; Subroutine - Send byte via serial port
; INPUTS:
;	w 	-	The byte to be sent via RS-232
;**************************************************************************
send_byte    	bank    serial

:wait        	test    tx_count                ;wait for not busy
		jnz     :wait                   ;

		not     w                       ;ready bits (inverse logic)
		mov     tx_high,w               ; store data byte
		setb    tx_low.7                ; set up start bit
		mov     tx_count,#10            ;1 start + 8 data + 1 stop bit
		RETP                            ;leave and fix page bits

;**************************************************************************
; Subroutine - Send string pointed to by address in W register
; INPUTS:
;	w	-	The address of a null-terminated string in program
;			memory
; OUTPUTS:
; 	outputs the string via. RS-232
;**************************************************************************
send_string	bank	serial
 		mov     string,w                ;store string address
:loop        	mov     w,string                ;read next string character
		mov     m,#3                    ; with indirect addressing
		iread                           ; using the mode register
		mov     m,#$F                   ;reset the mode register
		test    w                       ;are we at the last char?
		snz                             ;if not=0, skip ahead
		RETP                            ;yes, leave & fix page bits
		call    send_byte               ;not 0, so send character
		inc     string                  ;point to next character
		jmp     :loop                   ;loop until done

;**************************************************************************
; Subroutine - Make byte uppercase
; INPUTS:
;	byte	-	The byte to be converted
; OUTPUTS:
;	byte	-	The uppercase byte
;**************************************************************************
uppercase    	stc
		csae	  byte,#'a'            	;if byte is lowercase, then skip ahead
		RETP
		stc
		sub     byte,#'a'-'A'           ;change byte to uppercase
		RETP                            ;leave and fix page bits
;**************************************************************************
; Subroutine - Disable the outputs
; Load DC value into PPM and disable the output switch.
;**************************************************************************
disable_o
		bank	PPM_bank	; input mode.
		mov	D_to_A_val,#128	; put 2.5V DC on PPM output pin
		retp
;**************************************************************************
org	$600			; These subroutines are on page 3.
;**************************************************************************
; DTMF transmit functions/subroutines
;**************************************************************************
;**************************************************************************
DTMF_TABLE	; DTMF tone constants
; This routine returns with the constant used for each of the frequency
; detectors.
; INPUT:	w	-	Index into the table (0-15 value)
; OUTPUT:	w	-	Constant at that index
;**************************************************************************
		clc
		jmp	PC+w
		retw	f697_l
		retw	f697_h			
		retw	f770_l
		retw	f770_h
		retw	f852_l
		retw	f852_h	
		retw	f941_l
		retw	f941_h
		retw	f1209_l
		retw	f1209_h
		retw	f1336_l
		retw	f1336_h
		retw	f1477_l
		retw	f1477_h
		retw	f1633_l
		retw	f1633_h
;**************************************************************************
ASCII_TABLE	; Ascii value at index (0-15)
; INPUT:	w	-	Index into the table (0-15 value)
; OUTPUT:	w	-	Constant at that index
;**************************************************************************
		clc
		jmp	PC+w
		retw	'1'
		retw	'2'			
		retw	'3'
		retw	'A'
		retw	'4'
		retw	'5'	
		retw	'6'
		retw	'B'
		retw	'7'
		retw	'8'
		retw	'9'
		retw	'C'
		retw	'*'
		retw	'0'
		retw	'#'
		retw	'D'
;**************************************************************************
index_2_digit
; This subroutine converts a digit from 0-9 or a '*' or a '#' to a table 
; lookup index which can be used by the load_frequencies subroutine.  To use
; this routine, pass it a value in the 'byte' register.  No invalid digits
; are used. (A, B, C, or D)
;**************************************************************************
		call	ASCII_TABLE
		retp
;**************************************************************************
digit_2_index
; This subroutine converts a digit from 0-9 or a '*' or a '#' to a table 
; lookup index which can be used by the load_frequencies subroutine.  To use
; this routine, pass it a value in the 'byte' register.  No invalid digits
; are used. (A, B, C, or D)
;**************************************************************************
		bank	serial
		clr	temp
:loop
		mov	w,temp
		call	ASCII_TABLE
		xor	w,byte
		jz	:done
		inc	temp
		jb	temp.4,:done
		jmp	:loop

:done		mov	w,temp
		retp
		
;**************************************************************************
load_frequencies
; This subroutine loads the frequencies using a table lookup approach.
; The index into the table is passed in the byte register.  The DTMF table
; must be in the range of $400 to $500.
;**************************************************************************
		mov	temp,w
		bank	sine_gen_bank

		mov	w,>>temp
		and	w,#%00000110
		call	DTMF_TABLE
		mov	freq_count_low,w

		mov	w,>>temp
		and	w,#%00000110
		inc	wreg
		call	DTMF_TABLE
		mov	freq_count_high,w

		rl	temp
		setb	temp.3
		mov	w,temp
		and	w,#%00001110
		mov	temp,w
		call	DTMF_TABLE
		mov	freq_count_low2,w

		mov	w,temp
		inc	wreg
		call	DTMF_TABLE
		mov	freq_count_high2,w
		retp		
		
;**************************************************************************
dial_it		; This subroutine puts out whatever frequencies were loaded
		; for 1000ms, and then stops outputting the frequencies.
;**************************************************************************
		bank	sine_gen_bank
		clr	sine_index
		clr	sine_index2
		enable_o 			; enable the output
		mov	w,#10
		call	@delay_10n_ms		; delay 30ms
		setb	dtmf_gen_en
		mov	w,#12
		call	@delay_10n_ms		; delay 100ms
		clrb	dtmf_gen_en
		call	@disable_o		; now disable the outputs
:end_dial_it	retp
;**************************************************************************
sine_generator1				;(Part of interrupt service routine)
; This routine generates a synthetic sine wave with values ranging
; from -32 to 32.  Frequency is specified by the counter.  To set the
; frequency, put this value into the 16-bit freq_count register:
; freq_count = FREQUENCY * 6.83671552 (@50MHz)
;**************************************************************************
		bank	sine_gen_bank
		
		clc
		add	freq_acc_low,freq_count_low
		add	freq_acc_high,freq_count_high
		sc
		jmp	:no_change
		inc	sine_index
		mov	w,sine_index
		and	w,#$1f
		call	sine_table
	
		mov	curr_sine,w		;1		; add the velocity to sin


:no_change

;**************************************************************************
sine_generator2						;(Part of interrupt service routine)
; This routine generates a synthetic sine wave with values ranging
; from -32 to 32.  Frequency is specified by the counter.  To set the
; frequency, put this value into the 16-bit freq_count register:
; freq_count = FREQUENCY * 6.83671552 (@50MHz)
;**************************************************************************
		bank	sine_gen_bank
		clc
		add	freq_acc_low2,freq_count_low2
		add	freq_acc_high2,freq_count_high2
		sc
		jmp	:no_change
		inc	sine_index2
		mov	w,sine_index2
		and	w,#$1f
		call	sine_table
		mov	curr_sine2,w
:no_change
		mov	D_to_A_val,curr_sine2			; mov sin2 into PPM0
		mov	sine2_temp,w			; mov the high_frequency sin wave's current value
		clc					 ; into a temporary register
		snb	sine2_temp.7			; divide temporary register by four by shifting right
		stc					 ; (for result = (0.25)(sin2))
		rr	sine2_temp
		clc
		snb	sine2_temp.7
		stc
		mov	w,>>sine2_temp
		clc
		add	D_to_A_val,w				; (1.25)(sin2) = sin2 + (0.25)(sin2)
		add	D_to_A_val,curr_sine			; add the value of SIN into the PPM output
		add	D_to_A_val,#128			; for result = PPM0 = 1.25*sin2 + 1*sin
		retp					; return with page bits intact
;******************************************************************************
sine_table
; The values in this table can be changed to increase/decrease the amplitude of
; the output sine wave.
;******************************************************************************
	clc
	jmp	pc+w
	retw	0
	retw	4
	retw	8
	retw	11
	retw	14
	retw	16
	retw	18
	retw	19
	retw	20
	retw	19
	retw	18
	retw	16
	retw	14
	retw	11
	retw	8
	retw	4
	retw	0
	retw	-4
	retw	-8
	retw	-11
	retw	-14
	retw	-16
	retw	-18
	retw	-19
	retw	-20
	retw	-19
	retw	-18
	retw	-16
	retw	-14
	retw	-11
	retw	-8
	retw	-4
;**************************************************************************
;******************************************************************************
;        Copyright © 1998 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.
;        
;        Scenix Semiconductor products are not authorized for use in life support
;        systems or under conditions where failure of the product would endanger
;        the life or safety of the user, except when prior written approval is
;        obtained from Scenix Semiconductor.
;******************************************************************************


file: /Techref/scenix/lib/io/dev/modem/bell_103_full_dup_1_13.SRC, 45KB, , updated: 2002/12/12 09:23, local time: 2024/4/17 18:36,
TOP NEW HELP FIND: 
3.145.12.1:LOG IN

 ©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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://www.sxlist.com/techref/scenix/lib/io/dev/modem/bell_103_full_dup_1_13.SRC"> scenix lib io dev modem bell_103_full_dup_1_13</A>

Did you find what you needed?

 

Welcome to sxlist.com!


Site supported by
sales, advertizing,
& kind contributors
just like you!

Please don't rip/copy
(here's why

Copies of the site on CD
are available at minimal cost.
 

Welcome to www.sxlist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .