⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fuzzy11a.asm

📁 Embedded magazine soure code for the year 1991
💻 ASM
字号:
*	Fuzzy Logic Inferrence Engine
*
*** Data structures and variables
*
	ORG	$0000		;Beginning of HC11 RAM
CURRENT_INS RMB	8		;Storage for 8 8-bit inputs
FUZ_OUTS	RMB	32		;Storage for fuzzy outputs
COG_OUTS	RMB	4		;Defuzzified outputs
LOWEST_IF RMB	1		;Holds min grade of IF parts
SUM_OF_FUZ RMB	2		;11-bit sum of fuzzy outs
SUM_OF_PROD RMB	3		;19-bit sum of products
COGDEX	RMB	1		;Current out # for COG loop 0->4
SUMDEX	RMB	1		;Index for sum loop 8->0

	ORG	$B600		Beginning of HC11 EEPROM
IN_MF_PTRS FDB	IN0MF		;Addr of MF data for input 0
	FDB	IN1MF		;Addr of MF data for input 1
	FDB	IN2MF		;Addr of MF data for input 2
	FDB	IN3MF		;Addr of MF data for input 3
	FDB	IN4MF		;Addr of MF data for input 4
	FDB	IN5MF		;Addr of MF data for input 5
	FDB	IN6MF		;Addr of MF data for input 6
	FDB	IN7MF		;Addr of MF data for input 7
*
* Input membership functions are defined by four 8-bit values per
* input label. Up to 8 labels per input so max size of MF data
* structure is 8*8*4=256 bytes. Unused labels take no space.
* Membership functions are trapezoids with the base greater than or
* equal to the top. Values are entered into this program as the
* X coordinates of 4 points but are stored as 2 points and 2 slopes.
* 
***** MACRO Definition for input membership functions
*
INMF	MACR	;For input membership functions
	FCB	\0	                    ;First inflection point
	IFNE \1-\0		              ;Check for divide by zero
	 FCB	($FF+((\1-\0)/3))/(\1-\0) ;If not, calc slope
	ENDC
	IFEQ \1-\0		              ;Check for divide by zero
	 FCB	$00	                    ;Indicates vertical slope
	ENDC
	FCB	\2	                    ;Third inflection point
	IFNE \3-\2		              ;Check for divide by zero
	 FCB	($FF+((\3-\2)/3))/(\3-\2) ;If not, calc slope
	ENDC
	IFEQ \3-\2		              ;Check for divide by zero
	 FCB	$00	                    ;Indicates vertical slope
	ENDC
	ENDM
*	
*****
INPUT_MFS EQU	*		   ;Input membership functions

IN0MF	EQU	*		         ;(0) ROTATION
	INMF	0,0,0,8*4	         ;	(0) STOPPED
	INMF	0,8*4,$FF,$FF        ;	(1) NOT_STOPPED

IN1MF	EQU	*		         ;(1) EXAMPLE1
	INMF	$20,$40,$60,$A0      ;	(0) TEST1

IN2MF	EQU	*		         ;(2) TEMPERATURE
	INMF	2*0,2*0,2*40,2*50	   ;	(0) COLD
	INMF	2*40,2*50,2*60,2*70  ;	(1) COOL
	INMF	2*60,2*70,2*80,2*90  ;	(2) WARM
	INMF	2*80,2*90,2*95,2*110 ;	(3) HOT
	INMF	2*90,2*110,$FF,$FF   ;	(4) VERY_HOT

IN3MF	EQU	*		         ;(3) DAYS_SINCE_RAIN
	INMF	$00,$00,$00,$08	   ;	(0) NONE
	INMF	$00,$10,$10,$18	   ;	(1) SHORT
	INMF	$10,$20,$28,$40	   ;	(2) MEDIUM
	INMF	$30,$40,$50,$60	   ;	(3) LONG
	INMF	$50,$70,$FF,$FF	   ;	(4) VERY_LONG

IN4MF	EQU	*		;Not used
IN5MF	EQU	*		;Not used
IN6MF	EQU	*		;Not used
IN7MF	EQU	*		;Not used

SGLTN_POS EQU	*		;Output singleton positions
OUT0MF	EQU	*		;(0) WATERING_TIME
	FCB	$00			;(0) CUT_OFF
	FCB	$10			;(1) DECREASE_GREATLY
	FCB	$40			;(2) DECREASE
	FCB	$80			;(3) NORMAL
	FCB	$B0			;(4) INCREASE
	FCB	$F0			;(5) INCREASE_GREATLY
	FCB	0,0		;Unused; Must fill 8 per output
OUT1MF	FCB	0,0,0,0,0,0,0,0	;Not used
OUT2MF	FCB	0,0,0,0,0,0,0,0	;Not used
OUT3MF	FCB	0,0,0,0,0,0,0,0	;Not used
*
* Each If part is of the form 00AA AXXX where AAA is a label (0-7)
* and XXX is an input (0-7). If parts are connected by ANDs. A rule
* may have any number of if parts (usually 2-8). Then parts are of
* the form 100Y YCCC where the MSB set indicates a then part, YY is
* the output number (0-3), and CCC is the output label (singleton
* 0-7). A rule may have any number of then parts (usually 1 or 2).
* A $FF indicates the end of a series of rules (number not limited).
*  
*	FCB	INx + 8*LABa	;If input XXX is label AAA
*	FCB	$80+8*OUTy+LABc	;Then output YY is label CCC

RULE_START EQU	*		;Start of first rule
* Example rule: If TEMPERATURE is VERY_HOT and DAYS_SINCE_RAIN is LONG
* Then WATERING_TIME is INCREASE_GREATLY
RULE_1	FCB	2+(8*4),3+(8*3),$80+(8*0)+5
END_OF_RULE FCB	$FF

***** Fuzzy Inferrence Engine Starts Here
*
	ORG	$B66B
INFER_TOP LDX	#FUZ_OUTS	;Point at first fuzzy output
	LDAA	#32		;32 fuzzy outputs
CLR_OUTS	CLR	0,X		;Clear a fuzzy output
	INX			;Point at next
	DECA			;Loop index
	BNE	CLR_OUTS		;Continue till all fuzzy outs 0
	LDY	#RULE_START	;Point to start of 1st rule
RULE_TOP	LDAA	#$FF		;Begin processing rule string
	STAA	LOWEST_IF	;Will hold grade of min if part
IF_LOOP	LDAB	0,Y		;Get rule byte 00AA AXXX; If X is A
	BMI	THEN_LOOP	;If MSB=1, exit to then loop
	LDX	#CURRENT_INS	;Point at current input data area
	ANDB	#$07		;Save only input number
	PSHB			;Will need input # again
	ABX			;Point to specific input data
	LDAA	0,X		;Get current input data
	LDX	#IN_MF_PTRS	;Point at offsets for input MFs
	PULB			;Recover input number 0000 0XXX
	ABX			;Point at pointer for this input #
	LDX	0,X		;Get pointer into MF data area
	LDAB	0,Y		;Get rule if part 00AA AXXX
	ANDB	#$38		;00AA A000 is 8 times AAA
	LSRB			;000A AA00 4 times AAA
	ABX			;X points at MF points & slopes
	CMPA	0,X		;Compare input data to MF pt1
	BHS	NOT_SEG0		;Branch if not segment zero
	CLRB			;In seg 0 grade is zero
	BRA	HAVE_GRADE	;Have grade of membership
NOT_SEG0	CMPA	2,X		;Compare input data to MF pt2
	BHI	IS_SEG2		;Branch if segment two
	LDAB	1,X		;Slope1 -> B
	BEQ	JAM_FF		;If vert slope, jam $FF
	SUBA	0,X		;Input value - pt1 -> A
	MUL			;Grade in B if D < $100
	CPD	#$100		;Check for overflow
	BLO	HAVE_GRADE	;If < $100 grade OK in B
JAM_FF	LDAB	#$FF		;Else limit B to $FF
	BRA	HAVE_GRADE	;Have grade of membership
IS_SEG2	LDAB	3,X		;Slope2 -> B
	SUBA	2,X		;Input value - pt2 -> A
	MUL			;Grade in B if D < $100
	CPD	#$100		;Check for overflow
	BLO	B_OK		;If < $100 value in B OK
	LDAB	#$FF		;Else limit B to $FF
B_OK	LDAA	#$FF		;Grade should be $FF - (B)
	SBA			;Grade of membership in B
HAVE_GRADE CMPB	LOWEST_IF	;Is grade lowest so far ?
	BHS	NOT_LOWR		;Branch if not lower
	STAB	LOWEST_IF	;If lower, replace lowest if
	BNE	NOT_LOWR		;Skip ahead if not zero
FIND_THEN INY			;Adv rule pointer to then part
	LDAB	0,Y		;Get next rule byte
	BPL	FIND_THEN	;MSB set means its a then part
FIND_IF	INY			;Adv rule pointer to if part
	LDAB	0,Y		;Get next rule byte
	BPL	RULE_TOP		;MSB clear means its an if part
	CMPB	#$FF		;$FF is no more rules marker
	BNE	FIND_IF		;Continue looking for if or $FF
	BRA	DEFUZ		;When all rules done, go defuzzify
NOT_LOWR	INY			;Point to next rule byte
	BRA	IF_LOOP		;Continue for all if parts
THEN_LOOP LDX	#FUZ_OUTS	;Point at fuzzy outputs
	ANDB	#$1F		;Save 8 times out # + label #
	ABX			;X points at fuzzy output
	LDAA	LOWEST_IF	;Grade of membership for rule
	CMPA	0,X		;Compare to fuzzy output
	BLO	NOT_HIER		;Branch if not higher
	STAA	0,X		;Grade is higher so update
NOT_HIER	INY			;Point to next rule byte
	LDAB	0,Y		;Get rule byte
	BMI	CHK_END		;If MSB=0 its a new rule
	JMP	RULE_TOP		;Else process next rule byte
CHK_END	CMPB	#$FF		;Check for end of rules flag
	BNE	THEN_LOOP	;If not $FF, must be a then part
DEFUZ	LDY	#SGLTN_POS	;Point at 1st output singleton
	LDX	#FUZ_OUTS	;Point at 1st fuzzy output
	CLR	COGDEX		;Loop index will run from 0->4
COG_LOOP	LDAB	#8		;8 fuzzy outs per COG output
	STAB	SUMDEX		;Inner loop runs 8->0
	LDD	#$0000		;Used for quicker clears
	STD	SUM_OF_FUZ	;Sum of fuzzy outputs
	STD	SUM_OF_PROD+1	;Low 16-bits of sum of products
	STAA	SUM_OF_PROD	;Upper 8-bits
SUM_LOOP	LDAB	0,X		;Get a fuzzy output
	CLRA			;Clear upper 8-bits
	ADDD	SUM_OF_FUZ	;Add to sum of fuzzy outputs
	STD	SUM_OF_FUZ	;Update RAM variable
	LDAA	0,X		;Get fuzzy output again
	LDAB	0,Y		;Get Output singleton position
	MUL			;Position times weight
	ADDD	SUM_OF_PROD+1	;Low 16-bits of sum of products
	STD	SUM_OF_PROD+1	;Update low 16-bits
	LDAA	SUM_OF_PROD	;Upper 8-bits
	ADCA	#0		;Add carry from 16-bit add
	STAA	SUM_OF_PROD	;Upper 8-bits of 24-bit sum
	INY			;Point at next singleton pos.
	INX			;Point at next fuzzy output
	DEC	SUMDEX		;Inner loop index
	BNE	SUM_LOOP		;For all labels this output
	PSHX			;Save index for now
	CLRA			;In case divide by zero
	LDX	SUM_OF_FUZ	;Demominator for divide
	BEQ	SAV_OUT		;Branch if denominator is 0
	TST	SUM_OF_PROD	;See if more than 16-bit
	BNE	NUM_BIG		;If not zero, # is > 16-bits
	LDD	SUM_OF_PROD+1	;Numerator for divide
	IDIV			;Result in low 8-bits of X
	XGDX			;Result now in B
	TBA			;Move result to A
	BRA	SAV_OUT		;Go save output
NUM_BIG	LDD	SUM_OF_PROD	;Numerator upper 16 of 24-bit
	TST	SUM_OF_PROD+2	;Check for rounding error
	BPL	NO_ROUND		;If MSB clear, don't round
	ADDD	#1		;Round numerator up 1
NO_ROUND	FDIV			;D/X -> X, use upper 8 of 16
	XGDX			;Result now in A
SAV_OUT	LDX	#COG_OUTS	;Point to 1st defuz output
	LDAB	COGDEX		;Curent output number
	ABX			;Point to correct output
	STAA	0,X		;Update defuzzified output
	PULX			;Recover index
	INCB			;Increment loop index
	STAB	COGDEX		;Update
	CMPB	#4		;Done with all four outs?
	BNE	COG_LOOP		;If not, continue loop

* Inference engine has completed one pass of all rules.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -