SPLatco Knowledge Base
Example program demonstrating how to interface with a SX10504
 
 
* For use with MMI202 and SX10504 *
* 2x16 LCD *
 
** Setup **
 
* The SX10504 is interfaced to the MMI202 over X-Wire protocol by setting the communications jumper to 
* 	the X position.
* No board ID jumpers are installed as the X-Wire address for the SX10504 is address 0.
* If it is a MMI202 the X-Wire cable is connected from the Spice connector on the MMI202 to the X1 connector on the SX10504.
* If it is a MMI202a the X-Wire cable is connected from the CN12 connector on the MMI202a to the X1 connector on the SX10504. 
* 10k thermistors are connected to the analog inputs and the associated jumpers are set to the T position.
 
** Program operation **
 
* The thermistor drive voltage is set to 10 volts.
 
* Conductivity Channels. 
* 	These can be triggered by causing conduction to ground.
* 	Input 0 on the MMI202 will toggle the Conductivity Control bit which will turn on and off all conductivity
*	channels.
 
* Pressing front panel button IN8 advances to the next screen.
 
* Analog Inputs.
*	From left to right fAI_AnIn0, fAI_AnIn1, fAI_AnIn2.
*	Input voltage is displayed for the analog inputs.
 
* Pressing front panel button IN8 advances to the next screen.
 
* Analog Outputs.
*	From left to right fAO_AnOut0, fAO_AnOut1.
*	Current output voltage is displayed for the analog outputs.
* 	Pressing front panel button IN12 increments AnOut0 by 1 volt.
* 	Pressing front panel button IN11 decrements AnOut0 by 1 volt.
* 	Pressing front panel button IN10 increments AnOut1 by 1 volt.
* 	Pressing front panel button IN9 decrements AnOut1 by 1 volt.
*	The voltage range is 0 to 10 Volts.
 
* If at any time there are Xwire communications errors the front panel LED on output 15 will light.
 
* Equates *
 
* XWire Receive data block *
* Data block of 13 bytes *
 
fAI_Anin0:		mequ		100,4	;Location where Analog Input 0 from SX10504 is returned. 
fAI_Anin1:		mequ		104,4	;Location where Analog Input 1 from SX10504 is returned. 
fAI_Anin2:		mequ		108,4	;Location where Analog Input 2 from SX10504 is returned. 
bCC_Conduct_Data:	mequ		112	;Bits 0-4 conductivity channels (reads back true when conducting). 
 						;Bit 7 = readings available bit (reads back true when reading ready).
 
* XWire Transmit data block *
* Data block of 13 bytes *
 
fAO_Anout0:		mequ		10,4	;Location where Analog Output 0 value is stored for SX10504 to take.
fAO_Anout1:		mequ		14,4	;Location where Analog Output 1 value is stored for SX10504 to take.
bAI_Thermistor_Drive:	mequ		18,4	;Location where Thermistor Drive value is stored for SX10504 to take.
bCC_CCB:		mequ		22	;Bits 0-6 conductivity channels time factor.
 						;Bit 7 disables ALL channels when set true.
 
* Input equates *
 
iCC_ConductToggle:	iequ		0	;this input is used to toggle the conductivity control bit, to force on/off conductivity testing.
iAO_AnOut0_Up_Btn:	iequ		12	;increments analog output 0 by 10%
iAO_AnOut0_Dn_Btn:	iequ		11	;decrements analog output 0 by 10%
iAO_AnOut1_Up_Btn:	iequ		10	;increments analog output 1 by 10%	
iAO_AnOut1_Dn_Btn:	iequ		9	;decrements analog output 1 by 10%
 
* Output Equates *
 
oXW_XWireError:		oequ		15	;LED turns on when there is an Xwire communication error.	
 
 *******************
 ** Program start **
 *******************
 
Start
 		XwireMaster 	XWireTab		;start xwire going
		launchtask	Analog_Out_Task		;start the Analog Output task running
		launchtask	Analog_In_Task		;start the Analog Input task running
		launchtask	Conductivity_Task	;start the Conductivity Task running
		launchtask	LCD_Task		;start the Display task running
		launchtask	Xwire_Task		;start the XWire error checking task running
		runtasksforever
 
 
 
 ************************
 ** Analog Output Task **
 ************************
 
* Entry points * 
 
AO_GET_AnOut0:
		frecallw	fAO_Anout0              ;recall user set analog out 0 voltage (returns value in W as a value 0-1)
		return
AO_GET_AnOut1:
		frecallw	fAO_Anout1              ;recall user set analog out 1 voltage (returns value in W as a value 0-1)   
                return
                
Analog_Out_Task:
 
AO0:
		yieldtask
		goifink		iAO_AnOut0_Up_Btn,AO1	;does the user wish to increase the voltage on AnOut 0?
		goifink		iAO_AnOut0_Dn_Btn,AO3	;does the user wish to decrease the voltage on AnOut 0?
 
		goifink		iAO_AnOut1_Up_Btn,AO5	;does the user wish to increase the voltage on AnOut 1?
		goifink		iAO_AnOut1_Dn_Btn,AO7	;does the user wish to decrease the voltage on AnOut 1?
		goto		AO0
 
 ;; AnOut0 ;;
 
AO1:
		frecallq	fAO_Anout0		;limit check to prevent attempting to set voltage higher than maximum
		floadw		.9
		fsub
		fgoifpos	AO2
 		
		frecallq	fAO_Anout0		;below upper limit so increment AnOut 0 value by 10%
		floadw		.1
		fadd
		fstore		fAO_Anout0
		goto		AO0
AO2:
		floadw		1			;reached limit so increment no further
		fstore		fAO_Anout0	
		goto		AO0
AO3:
		frecallq	fAO_Anout0		;limit check to prevent attempting to set voltage lower than minimum
		floadw		.1
		fsub
		fgoifneg	AO4
 
		frecallq	fAO_Anout0		;above lower limit so decrement AnOut 0 value by 10%
		floadw		.1
		fsub
		fstore		fAO_Anout0
		goto		AO0
AO4:
		floadw		0			;reached limit so decrement no further
		fstore		fAO_Anout0	
		goto		AO0
 
 ;; AnOut1 ;;
 
AO5:
		frecallq	fAO_Anout1		;limit check to prevent attempting to set voltage higher than maximum
		floadw		.9
		fsub
		fgoifpos	AO6
 		
		frecallq	fAO_Anout1		;below upper limit so increment AnOut 0 value by 10%
		floadw		.1
		fadd
		fstore		fAO_Anout1
		goto		AO0
AO6:
		floadw		1			;reached limit so increment no further
		fstore		fAO_Anout1	
		goto		AO0
AO7:
		frecallq	fAO_Anout1		;limit check to prevent attempting to set voltage lower than minimum
		floadw		.1
		fsub
		fgoifneg	AO8
 
		frecallq	fAO_Anout1		;above lower limit so decrement AnOut 0 value by 10%
		floadw		.1
		fsub
		fstore		fAO_Anout1
		goto		AO0
AO8:
		floadw		0			;reached limit so decrement no further
		fstore		fAO_Anout1	
		goto		AO0
 
 
 ***********************
 ** Analog Input Task **
 ***********************
 
* Define Memory *
 		
fAI_AnalogVal0:			defFloat		;Where the data from the returned analog reading is stored as a voltage.
fAI_AnalogVal1:			defFloat		
fAI_AnalogVal2:			defFloat		
 
* Entry points *
 
AI_GET_AnIn0:
		frecallw	fAI_AnalogVal0		;display task gets the analog input voltage value. (Return in W as value 0-5V)
		return
AI_GET_AnIn1:
		frecallw	fAI_AnalogVal1	
		return
AI_GET_AnIn2:
		frecallw	fAI_AnalogVal2	
		return
 
Analog_In_Task:
		floadw		.5			;set thermistor drive voltage to 10 volts 
		fstore		bAI_Thermistor_Drive
		pause		200			;allow the drive voltage to settle
AI0:
		yieldtask
		frecallw	fAI_Anin0		;get the analog reading from AnIn channel 0.
		floadq		5			;load Q with maximum possible analog input voltage. (5 volts)
		fmul					;multiply to convert to volts.
		fstore 		fAI_AnalogVal0		;store calculation.
 
		frecallw	fAI_Anin1		;get the analog reading from AnIn channel 1.
		floadq		5			;load Q with maximum possible analog input voltage. (5 volts)
		fmul					;multiply to convert to volts.
		fstore 		fAI_AnalogVal1		;store calculation.
 
		frecallw	fAI_Anin2		;get the analog reading from AnIn channel 2.
		floadq		5			;load Q with maximum possible analog input voltage. (5 volts)
		fmul					;multiply to convert to volts.
		fstore 		fAI_AnalogVal2		;store calculation.
		goto		AI0
 
 *******************************
 ** Conductivity Channel Task **
 *******************************
 
* Define Memory *
 
bCC_Conduct_Ch1:	defbyte				;byte is true when channel is conducting and is false when it is not.
bCC_Conduct_Ch2:	defbyte				
bCC_Conduct_Ch3:	defbyte				
bCC_Conduct_Ch4:	defbyte					
bCC_Conduct_Ch5:	defbyte					
 
* Entry points *
 
CC_GET_CondCh1:
		recall		bCC_Conduct_Ch1		;returns a true in X if conducting and false if not conducting.
		return
CC_GET_CondCh2:
		recall		bCC_Conduct_Ch2		
		return
CC_GET_CondCh3:
		recall		bCC_Conduct_Ch3		
		return
CC_GET_CondCh4:
		recall		bCC_Conduct_Ch4		
		return
CC_GET_CondCh5:
		recall		bCC_Conduct_Ch5		
		return
 
Conductivity_Task:
                loadx		%00111011		;enable conductivity testing by clearing bit 7.
							;set the conductivity time factor by setting appropriate bits of 0-6. (59 + 1) x .05 = 3 seconds.
		store		bCC_CCB
CC0:							
		yieldtask
		goifink		iCC_ConductToggle,CC1	;toggle the conductivity control bit to enable/disable conductivity channels.
		goto		CC3
CC1:
		recall		bCC_CCB
		loadx		%10000000
		andm					;separate the conductivity control 'bit' out of the Conductivity Control 'Byte'
		goift		CC2
 		
		recall		bCC_CCB			;bit previously not set so OR %10000000 with CCB to set bit.
		loadx		%10000000
		orm
		store		bCC_CCB
		goto		CC3
CC2:
		recall		bCC_CCB			;bit previously was set so AND %01111111 with CCB to Clear bit.
		loadx		%01111111
		andm
		store		bCC_CCB
CC3:
 
 ;; Check if reading is valid ;;
 
		recall		bCC_Conduct_Data
		loadx		%10000000
		andm
		goiff		CC0			;if bit 7 is true then conductivity channel readings are stable and ready to be read.
 
 ;; Check conductivity channels ;;
 
		recall		bCC_Conduct_Data		;check conductivity channel 5
		loadx		%00010000		;mask all unwanted bits
		andm					
		store		bCC_Conduct_Ch5		;store channel status
 
		recall		bCC_Conduct_Data		;check conductivity channel 4
		loadx		%00001000		;mask all unwanted bits
		andm
		store		bCC_Conduct_Ch4		;store channel status
 
		recall		bCC_Conduct_Data		;check conductivity channel 3
		loadx		%00000100		;mask all unwanted bits
		andm
		store		bCC_Conduct_Ch3		;store channel status
 
		recall		bCC_Conduct_Data		;check conductivity channel 2
		loadx		%00000010		;mask all unwanted bits
		andm
		store		bCC_Conduct_Ch2		;store channel status
 		
		recall		bCC_Conduct_Data		;check conductivity channel 1
		loadx		%00000001		;mask all unwanted bits
		andm
		store		bCC_Conduct_Ch1		;store channel status
		goto		CC0
 
 ******************
 ** Display Task **
 ******************
 
* Input equates *
 
iLCD_Cycle:	iequ		8			;this input is used to cycle the data on the LCD
 
LCD_Task:
		oblcd_CLS
        		
 ;; Display Conductivity channels ;;
        		
LCD0:           
                yieldtask
		goifink		iLCD_Cycle,LCD10	;if toggle button is pressed change LCD display
		oblcd_setcur	0,0
		;		"0123456789012345"
		oblcd_text	"Chan: 1 2 3 4 5 "
		oblcd_setcur	1,0
		oblcd_text	"Cond: "
		gosub		CC_GET_CondCh1		;get channel 1 current conductivity status. Returned in X as true if conducting.
		goifF		LCD1
		oblcd_text	"Y "			;yes channel is conducting
		goto		LCD2		
LCD1:		
		oblcd_text	"N "			;no channel is not conducting		
LCD2:
		gosub		CC_GET_CondCh2		;get channel 2 current conductivity status. Returned in X as true if conducting.
		goifF		LCD3
		oblcd_text	"Y "			;yes channel is conducting
		goto		LCD4		
LCD3:		
		oblcd_text	"N "			;no channel is not conducting		
LCD4:
		gosub		CC_GET_CondCh3		;get channel 3 current conductivity status. Returned in X as true if conducting.
		goifF		LCD5
		oblcd_text	"Y "			;yes channel is conducting
		goto		LCD6		
LCD5:		
		oblcd_text	"N "			;no channel is not conducting		
LCD6:
		gosub		CC_GET_CondCh4		;get channel 4 current conductivity status. Returned in X as true if conducting.
		goifF		LCD7
		oblcd_text	"Y "			;yes channel is conducting
		goto		LCD8		
LCD7:		
		oblcd_text	"N "			;no channel is not conducting		
LCD8:
		gosub		CC_GET_CondCh5		;get channel 5 current conductivity status. Returned in X as true if conducting.
		goifF		LCD9
		oblcd_text	"Y "			;yes channel is conducting
		goto		LCD0		
LCD9:		
		oblcd_text	"N "			;no channel is not conducting	
		goto		LCD0
 
 ;; Display Analog Inputs ;;
	 
LCD10:
		yieldtask
		goifink		iLCD_Cycle,LCD_17	;if toggle button is pressed change LCD display
		oblcd_setcur	0,0
		;		"0123456789012345"
		oblcd_text	"Analog Inputs:  "
		oblcd_setcur	1,0
		gosub		AI_GET_AnIn0   
 
 ;; Check for LCD formatting issue ;;
  
                gosub           CF_Lower                ;check lower limit, FALSE will return in X if it is NOT a floating point value of 1
                goiff           LCD_11                  ;if returns TRUE check the upper limit
 
 ;; Analog In 0 ;;
  
 	        gosub	        AI_GET_AnIn0
                gosub           CF_Upper                ;check upper limit, FALSE will return in X if it is NOT a floating point value of 1        
                goiff           LCD_11                  ;if returns TRUE run the LCD formatting issue workaround        
        	oblcd_text	"1.0"                   ;value to display is floating point value of 1, therefore use OBLCD_Text instruction to display 1.0
                goto            LCD_12        
LCD_11: 
		gosub		AI_GET_AnIn0       
		oblcd_fdispw	3,1			;display AnIn channel 0 voltage
LCD_12:
		oblcd_text	"V "		
 
 ;; Analog In 1 ;;
  
		gosub		AI_GET_AnIn1
                gosub           CF_Lower                ;check lower limit, FALSE will return in X if it is NOT a floating point value of 1
                goiff           LCD_13                  ;if returns TRUE check the upper limit
	        gosub	        AI_GET_AnIn1
                gosub           CF_Upper                ;check upper limit, FALSE will return in X if it is NOT a floating point value of 1        
                goiff           LCD_13                  ;if returns TRUE run the LCD formatting issue workaround 
        	oblcd_text	"1.0"                   ;value to display is floating point value of 1, therefore use OBLCD_Text instruction to display 1.0
                goto            LCD_14        	
LCD_13:        
		gosub		AI_GET_AnIn1
		oblcd_fdispw    3,1			;display AnIn channel 1 voltage  
LCD_14:		
		oblcd_text	"V "	
 
 ;; Analog In 2 ;;
  
		gosub		AI_GET_AnIn2
                gosub           CF_Lower                ;check lower limit, FALSE will return in X if it is NOT a floating point value of 1
                goiff           LCD_15                  ;if returns TRUE run the LCD formatting issue workaround
	        gosub	        AI_GET_AnIn2
                gosub           CF_Upper                ;check upper limit, FALSE will return in X if it is NOT a floating point value of 1        
                goiff           LCD_15                  ;if returns TRUE run the LCD formatting issue workaround         
        	oblcd_text	"1.0"                   ;value to display is floating point value of 1, therefore use OBLCD_Text instruction to display 1.0
                goto            LCD_16
LCD_15:        
		gosub		AI_GET_AnIn2
		oblcd_fdispw    3,1			;display AnIn channel 2 voltage
LCD_16:
		oblcd_text	"V  "
		goto		LCD10
 
 ;; Display Analog Outputs ;;
 
LCD_17:
		yieldtask
		goifink		iLCD_Cycle,LCD0		;if toggle button is pressed change LCD display
		oblcd_setcur	0,0
		;		"0123456789012345"
		oblcd_text	"Analog Outputs: "
		oblcd_setcur	1,0
 
 ;; Analog Out 0 ;;
  	
	        gosub           AO_Get_AnOut0		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out	
  
 ;; Check for LCD formatting issue ;;
  
                gosub           CF_Lower                ;check lower limit, FALSE will return in X if it is NOT a floating point value of 1
                goiff           LCD_18                  ;if returns TRUE check the upper limit
	        gosub           AO_Get_AnOut0		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out
                gosub           CF_Upper                ;check upper limit, FALSE will return in X if it is NOT a floating point value of 1        
                goiff           LCD_18                  ;if returns TRUE run the LCD formatting issue workaround        
        	oblcd_text	"1.0"                   ;value to display is floating point value of 1, therefore use OBLCD_Text instruction to display 1.0
                goto            LCD_19        
LCD_18: 	
	        gosub           AO_Get_AnOut0		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out
		oblcd_fdispw    3,1			;display AnOut channel 0 voltage	
LCD_19:	
		oblcd_text	"V "    
 
 ;; Analog Out 1 ;;
  		
	        gosub           AO_Get_AnOut1		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out	
  
 ;; Check for LCD formatting issue ;;
  
                gosub           CF_Lower                ;check lower limit, FALSE will return in X if it is NOT a floating point value of 1
                goiff           LCD_20                  ;if returns TRUE check the upper limit
	        gosub           AO_Get_AnOut1		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out
                gosub           CF_Upper                ;check upper limit, FALSE will return in X if it is NOT a floating point value of 1        
                goiff           LCD_20                  ;if returns TRUE run the LCD formatting issue workaround        
        	oblcd_text	"1.0"                   ;value to display is floating point value of 1, therefore use OBLCD_Text instruction to display 1.0
                goto            LCD_21        
LCD_20: 	
	        gosub           AO_Get_AnOut1		;recalls user set voltage in W as a value 0-1
		floadq		10     			;load Q with maximum possible output voltage
		fmul					;multiply to get user set voltage out
		oblcd_fdispw    3,1			;display AnOut channel 0 voltage	
LCD_21:	
		oblcd_text	"V      "
		goto		LCD_17
 
 
;; Subroutines ;;
 
 ;; Check Floating point value of 1 ;;
   
CF_Lower:                                               ;following subroutines test if LCD formatting workaround needs to be run.
                floadq          .95
                fsub
                fgoifpos        CF_0
		loadx           255                     ;Return with X TRUE if above lower limit check, this will cause an upper limit check.
		goto            CF_1 
CF_0:          
                loadx           0                       ;Return FALSE in X if no action is needed
CF_1:           return
 
CF_Upper:
                floadq          1.05
                fsub
                fgoifneg        CF_2
		loadx           255                     ;Return with X TRUE if both limit checks find the floating point number is 1 and-
		goto            CF_3                    ;LCD format workaround needs to be run
CF_2:              
                loadx           0                       ;Return FALSE in X if no action is needed
CF_3:           return       
 
 
 ****************************
 ** Xwire Error Check Task **
 ****************************
 
Xwire_Task:
 
XW0:
		yieldtask
		xwiregeterrcount			;get the xwire error count
		goiff		XW1
		on		oXW_XWireError		;turn on error LED if there are XWire errors
		pause		1
		goto		XW0
XW1:		off		oXW_XWireError	
		goto		XW0
 
 
 ** X-Wire Master table **
 
        NVEM0
XWireTab:
        NV0Byte         0,10,13,100,13			;slave address 0, memory 10 is transmit data block, 13 bytes, 100 is Receive data block, 13 bytes.
        NV0Byte         255    ;End of table sentinel.