  ;  *** COMPILED WITH SX/B VERSION 1.51.03  09/21/2006 ***

                                 ;' =========================================================================
                                 ;'
                                 ;'   File...... ADC-UART-02.SXB
                                 ;'   Purpose... SX/B Programming Template
                                 ;'   Author.... Sparks-R-Fun 
                                 ;'   E-mail.... 
                                 ;'   Started...
                                 ;'   Updated... JUNE 11th 2007
                                 ;'
                                 ;' =========================================================================


                                 ;' -------------------------------------------------------------------------
                                 ;' Program Description
                                 ;' -------------------------------------------------------------------------
                                 ;' Tries to implement a continous sigma-delta ADC in and ISR along with a
                                 ;' 4800bps True mode serial UART.  This test version takes 50 ADC samples
                                 ;' and sends the raw date serially.  It can be run an an SX28 protoboard
                                 ;' using two 820K resistors and a 0.01uF capacitor.
                                 ;'
                                 ;' NOTE: For best viewing set tab spacing to four!
                                 ;'
                                 ;' -------------------------------------------------------------------------
                                 ;' Device Settings
                                 ;' -------------------------------------------------------------------------


DEVICE          SX28, OSCXT2, TURBO, STACKX, OPTIONX ;DEVICE          SX28, OSCXT2, TURBO, STACKX, OPTIONX

  ; DEFINE SYSTEM VARIABLES
__RAM         EQU  $00
RBC           EQU  $06
RBC_LSB       EQU  $06
RBC_MSB       EQU  $07
__PARAM1      EQU  $08
__PARAM2      EQU  $09
__PARAM3      EQU  $0A
__PARAM4      EQU  $0B
__PARAM5      EQU  $0C
__PARAMCNT    EQU  $0C
__WPARAM12    EQU  $08
__WPARAM12_LSB EQU  $08
__WPARAM12_MSB EQU  $09
__WPARAM23    EQU  $09
__WPARAM23_LSB EQU  $09
__WPARAM23_MSB EQU  $0A
__WPARAM34    EQU  $0A
__WPARAM34_LSB EQU  $0A
__WPARAM34_MSB EQU  $0B
__TRISA       EQU  $FA
TRIS_A        EQU  $FA
__TRISB       EQU  $FB
TRIS_B        EQU  $FB
__TRISC       EQU  $FC
TRIS_C        EQU  $FC
__INTPARAMFSR EQU  $F5
__REMAINDER   EQU  $08
__WREMAINDER  EQU  $08
__WREMAINDER_LSB EQU  $08
__WREMAINDER_MSB EQU  $09

; Define ShiftIn & ShiftOut Constants
LSBFIRST      EQU  0
MSBFIRST      EQU  1
MSBPRE        EQU  0
LSBPRE        EQU  1
MSBPOST       EQU  2
LSBPOST       EQU  3


                                 ;'FREQ            20_000_000
FREQ 50000000                    ;FREQ            50_000_000
__FREQMHZ     EQU  50

ID "Analog02"                    ;ID              "Analog02"



                                 ;' -------------------------------------------------------------------------
                                 ;' IO Pins
                                 ;' -------------------------------------------------------------------------

                                 ;' Serial Pins
SerialIn      EQU  RC.6          ;SerialIn        PIN RC.6 INPUT         

SerialOut     EQU  RC.7          ;SerialOut       PIN RC.7 OUTPUT        



                                 ;' ADC pins
                                 ;'InPin  			PIN RB.2 INPUT CMOS 
                                 ;'OutPin 			PIN RB.3 OUTPUT 
InPin         EQU  RC.1          ;InPin  			PIN RC.1 INPUT CMOS 

OutPin        EQU  RC.0          ;OutPin 			PIN RC.0 OUTPUT 



                                 ;' -------------------------------------------------------------------------
                                 ;' Constants
                                 ;' -------------------------------------------------------------------------
                                 ;' Establish Pin Directions, 0 = Output, 1 = Input

PinDirsRa     EQU  %0000         ;PinDirsRa		CON	%0000

PinDirsRb     EQU  %0000_1110    ;PinDirsRb		CON	%0000_1110	

                                 ;'PinDirsRc		CON	%0111_0000	
PinDirsRc     EQU  %0111_0010    ;PinDirsRc		CON	%0111_0010	


                                 ;'----------------
                                 ;' Logic Constants
                                 ;'----------------
True          EQU  1             ;True			CON 1				' True condition = 1

False         EQU  0             ;False			CON 0				' False condition = 0


                                 ;' -------------------------------------------------------------------------
                                 ;' Background Serial UART Constants
                                 ;' -------------------------------------------------------------------------
BAUD_RATE     EQU  4800          ;BAUD_RATE  		CON 4800             ' Set to desired baud rate

BAUD_RATE3    =  "14400"         ;BAUD_RATE3 		CON "14400"          ' Set to BAUD_RATE * 3 (cannot use computed constant)


                                 ;'# ZERO_STATE 		CON 0             	' Inverted serial mode, change to 0 for True serial mode.
                                 ;'# ONE_STATE  		CON 1             	' Inverted serial mode, change to 1 for True serial mode.

ZERO_STATE    EQU  1             ;ZERO_STATE 		CON 1                ' True serial mode, change to 1 for Inverted serial mode.

ONE_STATE     EQU  0             ;ONE_STATE  		CON 0                ' True serial mode, change to 0 for Inverted serial mode.



SEND_IDLE     EQU  40            ;SEND_IDLE  		CON 40               ' Value of serSendCnt when idle




                                 ;' -------------------------------------------------------------------------
                                 ;' Variables
                                 ;' -------------------------------------------------------------------------

                                 ;' System Status Variables
                                 ;'--------------------------
SystemStatus  EQU  0x0D          ;SystemStatus			VAR BYTE			' Track various states of the System Status.

NewADCValue   EQU  0x0E          ;  NewADCValue			VAR BYTE			' Indicates that a New ADC Value is ready.

serRecvFlag   EQU  SystemStatus.3 ;  serRecvFlag   		VAR	SystemStatus.3  ' This is set to 1 when a byte has been received.

ISRADCOnly    EQU  SystemStatus.5 ;  ISRADCOnly			VAR	SystemStatus.5	' Signals that the ISR should perform only the ADC code.




                                 ;' Background Serial UART Variables
                                 ;' --------------------------------

                                 ;' Interrupt Receive Variables
serRecvCnt    EQU  0x0F          ;serRecvCnt    	VAR BYTE                 ' This keeps track of the interrupt sample count.


serRecvData   EQU  0x10          ;serRecvData   	VAR BYTE                 ' This holds the completly received data byte.

SerialByte    EQU  serRecvData   ;	SerialByte	VAR serRecvData          ' This holds the completly received data byte.


serRecvWork   EQU  0x11          ;serRecvWork   	VAR BYTE                 ' This holds the data byte as it is being received.

                                 ;'#23 serRecvFlag   VAR Bit                  ' This is set to 1 when a byte has been received.

                                 ;' Interrupt send variables
serSendCnt    EQU  0x12          ;serSendCnt    	VAR BYTE                 ' This keeps track of which bit we are sending

serSendData   EQU  0x13          ;serSendData   	VAR BYTE                 ' This holds the value we are sending




                                 ;' ADC Variables
                                 ;'--------------
AnalogSampleCount  EQU  0x14     ;AnalogSampleCount		VAR BYTE			' Holds the Analog Sample Count.

AnalogHiRezCount  EQU  0x15      ;AnalogHiRezCount		VAR BYTE			' Holds the High byte of the Analog Sample Count.

                                 ;											'   Used when sampling more than 8 bits.

Temp1         EQU  0x16          ;Temp1					VAR BYTE			' Holds temporary values.

NumSamples    EQU  0x17          ;NumSamples				VAR BYTE			' Holds the number of ADC samples to send serially.

                                 ;											'   A variable was used instead of a constant
                                 ;											'   so that changes could easily be made
                                 ;											'   via the Debugger without reprogramming.

RAMBankB      EQU  0x30          ;RAMBankB				VAR BYTE (16)		' Holds memory regiter contents.

                                 ;'#30 	AnalogSampleCount	VAR RAMBankB(0)		' Holds the Analog Sample Count.
AnalogTempValue  EQU  RAMBankB+1 ;	AnalogTempValue		VAR RAMBankB(1)		' Holds the Analog Temporary Value.

AnalogHiRezTempValue  EQU  RAMBankB+2 ;	AnalogHiRezTempValue	VAR RAMBankB(2)		' Holds the Analog Value.

AnalogValue   EQU  RAMBankB+3    ;	AnalogValue			VAR RAMBankB(3)		' Holds the Analog Value.




                                 ;' Real Time Clock Variables
                                 ;'--------------------------
TIME          EQU  0x50          ;TIME           			VAR     Byte(16)

tix           EQU  TIME+0        ;tix             		VAR     TIME(0)



                                 ;' -------------------------------------------------------------------------
ORG $000                         ;INTERRUPT 28800        ' Sample at 3x the baud rate
  MOV FSR,#__INTPARAMFSR        
  MOV IND,M                     
  INC FSR                       
  MOV IND,__PARAM1              
  INC FSR                       
  MOV IND,__PARAM2              
  INC FSR                       
  MOV IND,__PARAM3              
  INC FSR                       
  MOV IND,__PARAM4              
  BANK $00                      

                                 ;' -------------------------------------------------------------------------

  JMP @ISR_Start                 ;Goto ISR_Start


__Process_UART:                  ;Process_UART			SUB 0, 0	' Perform the actual Processing of the UART.
  JMP @Process_UART             


ISR_Start:                       ;ISR_Start:

  CALL @__Process_UART           ;	Process_UART


ISR_Exit:                        ;ISR_Exit:

  MOV FSR,#__INTPARAMFSR         ;  RETURNINT 
  MOV M,IND                     
  INC FSR                       
  MOV __PARAM1,IND              
  INC FSR                       
  MOV __PARAM2,IND              
  INC FSR                       
  MOV __PARAM3,IND              
  INC FSR                       
  MOV __PARAM4,IND              
  MOV W,#39                     
  RETIW                         





                                 ;' =========================================================================
RESET __PROGSTART                ;  PROGRAM Start
__PROGSTART:                    
  JNB TO,@__RESTORETRIS         
  JB PD,@__POWERUP              
  CLR W                         
  MODE $09                      
  MOV !RB,W                     
  MOV FSR,W                     
  MODE $0F                      
  CJE FSR,#0,@__POWERUP         
  CJNE FSR,#$FF,@__RESTORETRIS  
__POWERUP:                      
  CLR RA                        
  CLR RB                        
  CLR RC                        
  MOV FSR,#$08                  
  SB FSR.3                      
  SETB FSR.4                    
  CLR IND                       
  IJNZ FSR,@$-3                 
  MOV FSR,#__TRISA              
  MOV IND,#255                  
  INC FSR                       
  MOV IND,W                     
  INC FSR                       
  MOV IND,W                     
__RESTORETRIS:                  
  MOV FSR,#__TRISA              
  MOV !RA,IND                   
  INC FSR                       
  MOV !RB,IND                   
  INC FSR                       
  MOV !RC,IND                   
  MOV !OPTION,#130              
  MODE $0F                      
  MOV FSR,#__TRISC              
  MOV W,#126                    
  MOV !RC,W                     
  MOV IND,W                     
  MODE $0D                      
  MOV W,#253                    
  MOV !RC,W                     
  CLR FSR                       
  JMP @Start                    
  ORG $+2  ; FOR DEBUGGER       

                                 ;' =========================================================================


                                 ;' -------------------------------------------------------------------------
                                 ;' Subroutine Declarations
                                 ;' -------------------------------------------------------------------------
__Serial_Send:                   ;Serial_Send	       		SUB 1, 1	' Send a byte to the Serial port.
  JMP @Serial_Send              




                                 ;' -------------------------------------------------------------------------
                                 ;' Program Code
                                 ;' -------------------------------------------------------------------------
Start:                           ;Start:

  MOV NumSamples,#50             ;	NumSamples = 50 				' Send 50 consecutive ADC samples.



Main:                            ;Main:


  MOV Temp1,#1                   ;	For Temp1 = 1 to NumSamples		' Loop through all samples.
__FOR_Temp1_1:                  


__DO_1:                          ;		Do 							' Wait for a New ADC Value.

  CJNE NewADCValue,#True,@__DO_1 ;		Loop Until NewADCValue = True



  MOV FSR,#AnalogValue           ;		Serial_Send AnalogValue		' Send the ADC Value serially.
  MOV __PARAM1,IND              
  BANK $00                      
  CALL @__Serial_Send           


  CLR NewADCValue                ;		NewADCValue = False			' Clear the New ADC Value flag.


  CJAE Temp1,NumSamples,@__NEXT_Temp1_1 ;	Next Temp1						' Repeat the loop as necessary.
  INC Temp1                     
  JNZ @__FOR_Temp1_1            
__NEXT_Temp1_1:                 


                                 ;  'Sleep								' Shutdown the SX.

  JMP @Main                      ;  GOTO Main






                                 ;' -------------------------------------------------------------------------
                                 ;' Subroutine Code
                                 ;' -------------------------------------------------------------------------
Process_UART:                    ;Process_UART:


                                 ; 	'----------------------
                                 ; 	' Take an Analog Sample
                                 ; 	'----------------------

                                 ; '	OutPin = ~InPin									' Toggle the Output Pin.

ASM                          ;asm

	mov	w,rc
	and	w,#$FE		;clear driver
	sb	rc.1                     
	or	w,#1		;set driver hi
	mov	rc,w
ENDASM                       ;endasm


;'  JNB InPin,@__ELSE_1            ; 	If InPin = 1 Then								' Check for a High value.
  JNB OutPin,@__ELSE_1            ; 	If InPin = 1 Then								' Check for a High value.

  MOV FSR,#AnalogTempValue       ; 		Inc AnalogTempValue							' Increment the Temporary Value.
  INC IND                       
  BANK $00                      


  MOV FSR,#AnalogTempValue       ; 		If AnalogTempValue = 0 Then					' Check for value rollover.
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#0,@__ELSE_2    

  MOV FSR,#AnalogHiRezTempValue  ; 			Inc AnalogHiRezTempValue				' Increment the rollover value.
  INC IND                       
  BANK $00                      

__ELSE_2:                        ; 		EndIf
__ENDIF_2:                      

__ELSE_1:                        ; 	EndIf
__ENDIF_1:                      


  DJNZ AnalogSampleCount,@DoneSampling ; 	DJNZ AnalogSampleCount, DoneSampling			' Check for Count rollever.

  DJNZ AnalogHiRezCount,@DoneSampling ; 		DJNZ AnalogHiRezCount, DoneSampling			' Check for extra counts completion.


  MOV AnalogHiRezCount,#16       ; 			AnalogHiRezCount = 16					' Set for an additional four bits.


  MOV FSR,#AnalogTempValue       ; 			AnalogTempValue = AnalogTempValue SHR 4	' Drop the four lowest bits
  CLC                           
  RR IND                        
  CLC                           
  RR IND                        
  CLC                           
  RR IND                        
  CLC                           
  RR IND                        
  BANK $00                      

  MOV FSR,#AnalogHiRezTempValue  ; 			AnalogHiRezTempValue = AnalogHiRezTempValue SHL 4		' Adjust the four highest bits
  CLC                           
  RL IND                        
  CLC                           
  RL IND                        
  CLC                           
  RL IND                        
  CLC                           
  RL IND                        
  BANK $00                      

  MOV FSR,#AnalogHiRezTempValue  ; 			AnalogValue = AnalogTempValue + AnalogHiRezTempValue	' Update the Analog Value
  MOV __PARAM3,IND              
  MOV FSR,#AnalogTempValue      
  ADD __PARAM3,IND              
  MOV FSR,#AnalogValue          
  MOV IND,__PARAM3              
  BANK $00                      


  MOV NewADCValue,#True          ;			NewADCValue = TRUE				' ' Indicates that a New ADC Value is ready.

  MOV FSR,#AnalogTempValue       ; 			AnalogTempValue = 0				' Clear the Analog sample Value.
  CLR IND                       
  BANK $00                      

  MOV FSR,#AnalogHiRezTempValue  ; 			AnalogHiRezTempValue = 0		' Clear the oversampled Analog sample Value.
  CLR IND                       
  BANK $00                      


DoneSampling:                    ; DoneSampling:

                                 ; 	'----------------------




                                 ;'  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  JB ISRADCOnly,@__ELSE_3        ;If ISRADCOnly = FALSE Then					' Determine if the UART and internal clock code

                                 ;											'   should also run.
                                 ;											' This allows the UART to run at half the ISR rate.
                                 ;'  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

                                 ;'----------------------
                                 ;' Check Serial Receiver
                                 ;'----------------------
                                 ;  ' Are we waiting for the stop bit ?
  CJNE serRecvCnt,#0,@__ELSE_4   ;  IF serRecvCnt = 0 THEN

  JB SerialIn,@__ELSE_5          ;    IF SerialIn = ONE_STATE THEN

                                 ;      ' Got stop bit
  MOV serRecvCnt,#1              ;      serRecvCnt = 1

  CLR serRecvWork                ;      serRecvWork = 0

__ELSE_5:                        ;    ENDIF
__ENDIF_5:                      

  JMP @__ENDIF_4                 ;  ELSE
__ELSE_4:                       

  DJNZ serRecvCnt,@RecvDone      ;    DJNZ serRecvCnt,RecvDone

  CJNE serRecvWork,#0,@__ELSE_6  ;    IF serRecvWork = 0 THEN

                                 ;      ' Waiting for start bit
  JNB SerialIn,@__ELSE_7         ;      IF SerialIn = ZERO_STATE THEN


                                 ;        ' Got start bit
  SETB serRecvWork.7             ;        serRecvWork.7 = 1              ' Prime value

  MOV serRecvCnt,#4              ;        serRecvCnt = 4                 ' Get 1st data bit 1.333 bit-times from now

  JMP @__ENDIF_7                 ;      ELSE
__ELSE_7:                       

                                 ;        ' Didn't get start bit, so check next interrupt
  MOV serRecvCnt,#1              ;        serRecvCnt = 1

__ENDIF_7:                       ;      ENDIF

  JMP @__ENDIF_6                 ;    ELSE
__ELSE_6:                       

                                 ;      ' Getting data bits
  MOVB serRecvCnt.0,serRecvWork.0 ;      serRecvCnt.0 = serRecvWork.0     ' Keep value of last bit to see if we are done.      

   RR serRecvWork                ;      \ RR serRecvWork                 ' Shift bits in value, used because ">>" operator uses __PARAM1

  JB SerialIn,@__ELSE_8          ;      IF SerialIn = ONE_STATE THEN

  SETB serRecvWork.7             ;        serRecvWork.7 = 1

  JMP @__ENDIF_8                 ;      ELSE
__ELSE_8:                       

  CLRB serRecvWork.7             ;        serRecvWork.7 = 0

__ENDIF_8:                       ;      ENDIF

                                 ;      ' Check if this was the last data bit
  JNB serRecvCnt.0,@__ELSE_9     ;      IF serRecvCnt.0 = 1 THEN

  MOV serRecvData,serRecvWork    ;        serRecvData = serRecvWork      ' Copy data byte

  SETB serRecvFlag               ;        serRecvFlag = 1                ' Indicate that we have recieved a data byte

  CLR serRecvCnt                 ;        serRecvCnt = 0                 ' Indicate that we have to wait for stop bit next time

  CLR serRecvWork                ;        serRecvWork = 0                ' Clear data byte to indicate start bit has not been received yet

  JMP @__ENDIF_9                 ;      ELSE
__ELSE_9:                       

  MOV serRecvCnt,#3              ;        serRecvCnt = 3                 ' Get next data bit 1 bit-time from now

__ENDIF_9:                       ;      ENDIF

__ENDIF_6:                       ;    ENDIF

__ENDIF_4:                       ;  ENDIF

                                 ;'----------------------
RecvDone:                        ;RecvDone:



                                 ;'--------------------
                                 ;' Check Serial Sender
                                 ;'--------------------
  CJAE serSendCnt,#SEND_IDLE,@__ELSE_10 ;  IF serSendCnt < SEND_IDLE THEN       ' Are we sending ?

  JB serSendCnt.0,@__ELSE_11     ;    IF serSendCnt.0 = 0 THEN           ' Only send when bit 0 and 1 are zero (every 4 counts)

  JB serSendCnt.1,@__ELSE_12     ;      IF serSendCnt.1 = 0 THEN

  CJNE serSendCnt,#0,@__ELSE_13  ;        IF serSendCnt = 0 THEN         ' If count is zero we need to send the start bit

                                 ;          ' Send start bit
  SETB SerialOut                 ;          SerialOut = ZERO_STATE       ' Start bit is a "0"

  JMP @__ENDIF_13                ;        ELSEIF serSendCnt < 36 THEN    ' If count is < 36 then we are sending data bits
__ELSE_13:                      
  CJAE serSendCnt,#36,@__ELSE_14

                                 ;          ' Send data bits
  JB serSendData.0,@__ELSE_15    ;          IF serSendData.0 = 0 THEN    ' Send bit value that is in bit position zero

  SETB SerialOut                 ;            SerialOut = ZERO_STATE

  JMP @__ENDIF_15                ;          ELSE
__ELSE_15:                      

  CLRB SerialOut                 ;            SerialOut = ONE_STATE

__ENDIF_15:                      ;          ENDIF

   RR serSendData                ;          \ RR serSendData'            ' Used because ">>" operator uses __PARAM1

  JMP @__ENDIF_13                ;        ELSE
__ELSE_14:                      

                                 ;         ' Send stop bit
  CLRB SerialOut                 ;         SerialOut = ONE_STATE         ' Stop bit is a "1" 

__ENDIF_13:                      ;        ENDIF

  INC serSendCnt                 ;        INC serSendCnt                 ' Bump count because we want to send a bit every 3 interrupts, but it easier to detect every 4 counts

__ELSE_12:                       ;      ENDIF
__ENDIF_12:                     

__ELSE_11:                       ;    ENDIF
__ENDIF_11:                     

  INC serSendCnt                 ;    INC serSendCnt

__ELSE_10:                       ;  ENDIF
__ENDIF_10:                     

                                 ;'--------------------




                                 ;	'----------------------------
                                 ;	' Update Real Time Clock Tick
                                 ;	'----------------------------
  MOV FSR,#tix                   ;  	INC tix    		
  INC IND                       
  BANK $00                      


  MOV FSR,#tix                   ; 	If tix = 144 Then
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#144,@__ELSE_16 

  MOV FSR,#tix                   ; 		tix = 0
  CLR IND                       
  BANK $00                      

__ELSE_16:                       ;	EndIf
__ENDIF_16:                     

                                 ;	'---------------------------------

__ELSE_3:                        ;EndIf									' End of conditional ISR code block.
__ENDIF_3:                      

                                 ;'  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

  XOR 0x0D,#%00100000            ;	ISRADCOnly = ~ISRADCOnly			' Toggle the run ADC code Only flag.

                                 ;										' This allows the UART to run at half the ISR rate.

  RETP                           ;Return

                                 ;'-------------------------------------------





                                 ;'-------------------------------------------
                                 ;' Send a Serial Byte via the Background UART
                                 ;'-------------------------------------------
Serial_Send:                     ;Serial_Send:

SendByte:                        ;SendByte:

__DO_2:                          ;  DO

  CJNE serSendCnt,#SEND_IDLE,@__DO_2 ;  LOOP UNTIL serSendCnt = SEND_IDLE

  MOV serSendData,__PARAM1       ;  serSendData = __PARAM1

  CLR serSendCnt                 ;  serSendCnt = 0

  RETP                           ;RETURN

                                 ;'-------------------------------------------

