Written some cool source code? Upload it to Programmer's Heaven.
*/
*/

View \FUZZ11B1.ASM

Fuzzy logic engine for the 68HC11

Submitted By: WEBMASTER
Rating: Not rated (Rate It)


*       Fuzzy Logic Inferrence Engine
*
** This is the third variation of this fuzzy engine. The first used
*  a macro and conditional assembly for entry of rules and MFs. It
*  also combined fuzzification with rule evaluation. The 2nd version
*  was more efficient because fuzzy ins are only calculated once.
*  Also a c program was written to simplify rule and MF entry rather
*  than a macro and conditional assembly which were not very
*  portable from one assembler to another. The 2nd version used fixed
data structures for 4 ins and 2 outs. This, the third version, is
* identical to the 2nd version, except that the input and output size
* is variable. The number of Inputs and Outputs is set by the Knowledge
* Base Generator (kbg_11b1.exe). KBG_11B1 counts the actual number of
* Inputs and Outputs that you defined and generates an assembly language
* define statement for this Inference Engine to use.
*
*** Data structures and variables
*
            ORG     $0000   ;Beginning of HC11 RAM
CURRENT_INS RMB     4       ;Storage for 4 8-bit inputs
FUZ_INS     RMB     (8*NUMINP)  ;Storage for fuzzy inputs
FUZ_OUTS    RMB     (8*NUMOUT)  ;Storage for fuzzy outputs
COG_OUTS    RMB     NUMOUT      ;Defuzzified outputs
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
LP_COUNT    RMB     1       ;Index for fuz loop
SUMDEX      RMB     1       ;Index for sum loop

            ORG     $B600   ;Beginning of HC11 EEPROM
* Add the output from KBG_11C.exe here.....

***** Fuzzy Inferrence Engine Starts Here
*
FUZZIFY     LDY     #FUZ_INS      ;Point at fuzzy input table
            LDX     #CURRENT_INS  ;Point at current input values
            LDD     2,X           ;Put input values on stack
            PSHB
            PSHA
            LDD     0,X
            PSHB
            PSHA

            LDX     #INPUT_MFS    ;Point at input MF specs
NXTIN_LP    PULA                  ;Get next current input value
            LDAB    #7            ;For 8 loop passes
            STAB    LP_COUNT      ;Initialize loop counter
GRAD_LOOP  EQU     *             ;Get grade for 1 label of 1 input

*******************************************************************
* GET_GRADE - Routine to project a discrete input value onto      *
*   the associated input membership function (fuzzification).     *
*   Enter with Input value in A register and X pointing at the    *
*   points and slopes defining the membership function.           *
*   Finishes with grade in B, X points at next MF spec (X+4)      *
*   and A is unchanged.                                           *
*******************************************************************
GET_GRADE   PSHA                  ;Save input value of A
            CLRB                  ;In case grade = 0
            SUBA    2,X           ;Input value D pt2 -> A
            BLS     NOT_SEG2      ;If input < pt2
            LDAB    3,X           ;Slope 2
            BEQ     HAV_GRAD      ;Skip if vert slope    
            MUL                   ;(In D pt1) * slp2 -> A:B
            TSTA                  ;Check for > $FF
            BEQ     NO_FIX        ;If upper 8 = 0
            CLRB                  ;Limit grade to 0
            BRA     HAV_GRAD      ;In limit region of seg 2
NO_FIX      SUBB    #$FF          ;B D $FF
            NEGB                  ;$FF D B
            BRA     HAV_GRAD      ;($FF D((In D pt2) * slp2))
NOT_SEG2    ADDA    2,X           ;Restore input value
            SUBA    0,X           ;Input value D pt1 -> A
            BLO     HAV_GRAD      ;In < pt1 so grade = 0
            LDAB    1,X           ;Slope 1
            BEQ     VERT_SLP      ;Skip if vert slope    
            MUL                   ;(In D pt1) * slp1 -> A:B
            TSTA                  ;Check for > $FF
            BEQ     HAV_GRAD      ;Result OK in B
VERT_SLP    LDAB    #$FF          ;Limit region or vert slope
HAV_GRAD    INX                   ;Point at next MF spec
            INX
            INX
            INX
            PULA                  ;Restore A register

            STAB    0,Y           ;Save @ fuzzy input
            INY                   ;Point at next
            DEC     LP_COUNT      ;
            BPL     GRAD_LOOP     ;For 8 labels of 1 input
            CMPY    #FUZ_INS+(8*NUMINP)   ;Done with all fuzzy ins?
            BNE     NXTIN_LP      ;If not, process next input
* Done with fuzzification, evaluate rules next

            LDX     #FUZ_OUTS     ;Point at first fuzzy output
            LDAA    #(8*NUMOUT)   ;Number of 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 a rule string
* A will hold grade of smallest (min) if part
IF_LOOP     LDAB    0,Y           ;Get rule byte 000X XAAA; If X is A
            BMI     THEN_LOOP     ;If MSB=1, exit to then loop
            INY                   ;Point at next rule byte
            LDX     #FUZ_INS      ;Point at fuzzy inputs
            ABX                   ;Point to specific fuzzy input
            CMPA    0,X           ;Is this fuzzy input lower?
            BHS     IF_LOOP       ;If not don't replace lowest
            LDAA    0,X           ;Replace lowest if
            BNE     IF_LOOP       ;Unless zero, do next rule byte
* A zero value fuzzy input makes rule completely not true
* so skip rest of if parts and all then parts to start of next rule
FIND_THEN   LDAB    0,Y           ;Get next rule byte
            BMI     FIND_IF       ;MSB set means its a then part
            INY                   ;Point at next rule byte
            BRA     FIND_THEN     ;Loop till pointing at 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

THEN_LOOP   LDX     #FUZ_OUTS     ;Point at fuzzy outputs
            ANDB    #$0F          ;Save 8 times out # + label #
            ABX                   ;X points at fuzzy output
* Grade of membership for rule is in A accumulator
            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                   ;Adv rule pointer to next byte
            LDAB    0,Y           ;Get rule byte
            BPL     RULE_TOP      ;If MSB=0 its a new rule
CHK_END     CMPB    #$FF          ;Check for end of rules flag
            BNE     THEN_LOOP     ;If not $FF, must be a then part

* All rules evaluated. Now defuzzify fuzzy outputs          
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->1
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    #NUMOUT       ;Done with outputs?
            BNE     COG_LOOP      ;If not, continue loop
*****
* Inference engine has completed one pass of all rules.
*****

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.
Resource Listings