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.