/*******************************************************************************
Copyright(c) 2000 - 2006 Analog Devices. All Rights Reserved.

By using this module you agree to the terms of the Analog Devices License
Agreement for DSP Software. 

********************************************************************************
Module name: median.asm
Label name: __median


Description:   For a detailed description, please refer to the file "readme.txt".
               which is included in the main project.

*******************************************************************************/
 .section    L1_code;
.global     __median;
.align       8;
    
__median:

    [--SP]=(R7:4,P5:3);
    P4=[SP+40];             // Address of output array
    P5=R0;                  // Address of input array
    M0=R0;
    P1=R2;                  // Number of columns
    P0=R2;
    P2=R1;                  // Number of rows
    P3=R2;                   
//////////////////// First Row  ///////////////////////////////////////////////
    LSETUP(FIRST_ROW_ST,FIRST_ROW_END)LC0=P1;
FIRST_ROW_ST:
        R0=B[P5++](Z);          
FIRST_ROW_END:
        B[P4++]=R0;
                            // output = input 
    P5=M0;                  // Address of input array
    R3=R2<<1 ||R0=B[P5++](Z);
                            // fetch first element 
    P1+=-2;                 // Col-2
    P2+=-2;                 // ROW-2;
    R3+=1;
    P3+=-1;                 // col -1
//////////////// Middle loop ///////////////////////////////////////
    LSETUP(ROW_ST,ROW_END)LC0=P2;
                            // loop counter == ROW-2 (M-2) 
    P2=R3;                  // 2*col
    R1=B[P5++](Z);          // fetch x01
    P5=P5+P1;               // increment to fetch x10
    R2=B[P5](Z);            // fetch x10
    P5-=P1;                 // modify to first row
ROW_ST:
        B[P4++]=R2;
                            // first element in each row output = input 
        LSETUP(COL_ST,COL_END)LC1=P1;
                            // loop counter=col-2 
COL_ST:     R3=R0+R1(NS)|| R2=B[P5](Z);
                            // add first two elements and fetch next data 
            P5=P5+P1;       // modify pointer to next row
            R3=R3+R2(NS);   // get total sum of 3 element
            R4=MAX(R0,R1);          
            R4=MAX(R4,R2);  // maximum of first row
            R1=MIN(R0,R1)||R0=B[P5++](Z);
            R6=MIN(R1,R2)||R1=B[P5++](Z);
                            // minimum of first row,fetch next row elements 
            R5=R4+R6;       // sum of max and min of first row
            R3=R3-R5(NS) ||R2=B[P5](Z);
                            // median value of first row
            P5=P5+P1;       // Increment pointer to 3rd row
            R5=R0+R1;         
            R5=R5+R2;       // sum of 3 elements in second row
            R7=MAX(R0,R1);
            R7=MAX(R7,R2);  // Maximum value of second row
            R0=MIN(R0,R1);
            R0=MIN(R0,R2);  // minimum value of second row
            R1=R0+R7;
            R5=R5-R1(NS);   // median value of second row
            R6=MAX(R6,R0)||R0=B[P5++](Z);
                            // Maximum value of first row MIN and second row MIN 
            I0=R6;
            R4=MIN(R4,R7)||R1=B[P5++](Z);
                            // Minimum of first row MAX and second row MAX 
            R7=R0+R1(NS) ||R2=B[P5](Z); 
            R7=R7+R2(NS);
            R6=MAX(R0,R1);
            R6=MAX(R6,R2);  // Maximum value of 3rd row
            R0=MIN(R0,R1);
            R0=MIN(R0,R2);  // Minimum of 3rd row
            R2=R0+R6;
            R7=R7-R2;       // Median value of 3rd row
            R2=I0;
            R4=MIN(R4,R6);  //X= MIN(MAX0,MAX1,MAX2)
            R6=MAX(R0,R2);  //Y= MAX(MIN0,MIN1, MIN2)
            R0=R3+R7;
            R1=R0+R5;       // SUM OF MED0,MED1 and MED2
            R0=MAX(R3,R7);
            R0=MAX(R0,R5);  // MAX(MED0.MED1,MED2)
            R2=MIN(R3,R7);
            R2=MIN(R2,R5);  // MIN(MED0,MED1,MED2)
            R2=R2+R0;
            R1=R1-R2(NS);   //Z= Median of (MED0,MED1,MED2)
            R2=R4+R6;
            R2=R2+R1;       // Sum of X,Y,Z
            P5-=P2;
            R3=MAX(R4,R6);
            R3=MAX(R3,R1);  // MAX(X,Y,Z)
            R4=MIN(R4,R6);
            R4=MIN(R4,R1);  // MIN(X,Y,Z)
            R4=R4+R3(NS)||R0=B[P5++](Z);
            R2=R2-R4(NS)||R1=B[P5++](Z);
                            // R2==median value of 9 elements 
COL_END:    B[P4++]=R2;
                            // store the result 
        P5=P5+P3;           // modify to starting of next row
        R0=B[P5++](Z);      // store least element of the row
        R2=B[P5--](Z);    
        B[P4++]=R0;         // store first element of next row
        P5-=P3;                      
        R0=B[P5++](Z); 
ROW_END:R1=B[P5++](Z);
                            // fetch first two elements 
    P5=P5+P1;
    
    LSETUP(LAST_ROW_ST,LAST_ROW_END)LC0=P0;
LAST_ROW_ST:
        R0=B[P5++](Z);
LAST_ROW_END:
        B[P4++]=R0;
                            // copy last row output == input 
    (R7:4,P5:3)=[SP++];
    RTS;
    NOP;                    // To avoid one stall if LINK or UNLINK happens to 
                            //be the  next instruction in the memory.
__median.end:                            
