• PicŪ Basic


  • Two Dimensional Arrays

    It can be very useful some times to work with two dimensional arrays. Using this new macro it's now possible. (For the 18F PICŪ devices only)

    '
    ' Two macros that simulate a 2 dimensional byte array load and retrieve
    ' The macros use NO variable RAM other that SFR registers, and use no Call Stack space.
    '
    ' For 16-bit core (18F) devices only. Using PROTON+ Version 3.03 Onwards.
    '
    ' This program can be tested using the PIC18_ALCD_VHB file in the ISIS simulator.

    Include "PROTON18_4.INC" ' Use the PROTON Dev board for the demonstration

    Dim INDEX1 as Byte ' \
    Dim INDEX2 as Byte ' Create some variables for the demo loop
    Dim BYTE_OUT as Byte ' /

    Symbol DIMENSION_1 = 10 ' Array dimension 1 size
    Symbol DIMENSION_2 = 10 ' Array dimension 2 size

    Dim XY_ARRAY[DIMENSION_1 * DIMENSION_2] as Byte ' Create an array large enough for all the elements
    Symbol XY_ARRAY_LENGTH = 10 ' The length of dimension 2 of the array


    '--------------------------------------------------------------------------------------
    ' Simulate a two part array XY_ARRAY[INDEX1 , INDEX2] = VALUE_IN
    ' The algorithm for accessing the elements is: -
    ' FSR0 = ARRAY_NAME
    ' FSR0 = FSR0 + INDEX2
    ' PROD = INDEX1 * INDEX2_LENGTH
    ' FSR0 = FSR0 + PROD

    ' Syntax: -
    ' MARRAY_OUT XY_ARRAY , INDEX2_LENGTH , [INDEX1 , INDEX2] , VALUE_IN

    ' Where: -
    ' ARRAY_NAME is the name of the array in question
    ' INDEX2_LENGTH is the second index's length
    ' INDEX1 is the first index value of the array
    ' INDEX2 is the second index value of the array
    ' VALUE_IN is the 8-bit value to place at the position in the array

    MARRAY_OUT MACRO- ARRAY_NAME, INDEX2_LENGTH, INDEX_1, INDEX_2, VALUE_IN

    #if(PRM_1 != BYTE_ARRAY_PTR)
    #error "Parameter 1 must be a BYTE ARRAY for MARRAY_OUT macro"
    EXITM
    #endif
    ASM-
    Lfsr 0,ARRAY_NAME ; Point FSR0 to the Array
    #if((PRM_4 == NUM8) || (PRM_4 == NUM16) || (PRM_4 == NUM32)) ; \
    Movlw INDEX_2 ; \
    #endif ; |
    #if((PRM_4 == BYTE) || (PRM_4 == WORD) || (PRM_4 == DWORD)) ; |
    #if(INDEX_2 <= BANKA_END) ; Get the second INDEX value into WREG
    Movf INDEX_2,W ; |
    #else ; |
    Movff INDEX_2,WREG ; /
    #endif ; /
    #endif
    Addwf FSR0L,F ; \
    Movlw 0 ; Add this to FSR0
    Addwfc FSR0H,F ; /

    #if((PRM_3 == NUM8) || (PRM_3 == NUM16) || (PRM_3 == NUM32)) ; \
    Movlw INDEX_1 ; \
    #endif ; |
    #if((PRM_3 == BYTE) || (PRM_3 == WORD) || (PRM_3 == DWORD)) ; |
    #if(INDEX_1 <= BANKA_END) ; |
    Movf INDEX_1,W ; Get the first INDEX into WREG
    #else ; |
    Movff INDEX_1,WREG ; |
    #endif ; /
    #endif ; /
    ENDASM-
    #if((PRM_2 != NUM8) && (PRM_2 != NUM16) && (PRM_2 != NUM32))
    #error "INDEX LENGTH must be a constant value for MARRAY_OUT macro"
    #endif
    ASM-
    Mullw INDEX2_LENGTH ; \
    Movf PRODL,W ; \
    Addwf FSR0L,F ; Calculate the offset within the array
    Movf PRODH,W ; /
    Addwfc FSR0H,F ; /
    ;
    ; At this point FSR0 is pointing to the correct element based on INDEX_1, INDEX_2 and INDEX2_LENGTH
    ;
    #if((PRM_5 == NUM8) || (PRM_5 == NUM16) || (PRM_5 == NUM32)) ; \
    #if(VALUE_IN == 0) ; \
    Clrf INDF0 ; |
    #else ; |
    #if(VALUE_IN == 255) ; |
    Setf INDF0 ; |
    #else ; |
    Movlw VALUE_IN ; Place the value into the element
    Movwf INDF0 ; |
    #endif ; |
    #endif ; |
    #endif ; |
    #if((PRM_5 == BYTE) || (PRM_5 == WORD) || (PRM_5 == DWORD)) ; |
    Movff VALUE_IN,INDF0 ; /
    #endif ; /
    #if(PRM_5 == FLOAT)
    #error "Floating point not supported with the MARRAY_OUT macro"
    #endif
    ENDASM-
    ENDM
    '--------------------------------------------------------------------------------------
    ' Simulate a two part array VARIABLE = XY_ARRAY [INDEX1 , INDEX2]
    ' The algorithm for accessing the elements is: -
    ' FSR0 = ARRAY_NAME
    ' FSR0 = FSR0 + INDEX2
    ' PROD = INDEX1 * INDEX2_LENGTH
    ' FSR0 = FSR0 + PROD

    ' Syntax:
    ' VARIABLE = MARRAY_IN XY_ARRAY , INDEX2_LENGTH , [INDEX1 , INDEX2]

    ' Where: -
    ' VARIABLE is the 8-bit value extracted from the array
    ' ARRAY_NAME is the name of the array in question
    ' INDEX2_LENGTH is the second index's length
    ' INDEX1 is the first index value of the array
    ' INDEX2 is the second index value of the array

    MARRAY_IN MACRO- ARRAY_NAME, INDEX2_LENGTH, INDEX_1, INDEX_2

    #if(PRM_1 != BYTE_ARRAY_PTR)
    #error "Parameter 1 must be a BYTE ARRAY for MARRAY_IN macro"
    EXITM
    #endif
    ASM-
    Lfsr 0,ARRAY_NAME ; Point FSR0 to the start of the ARRAY
    #if((PRM_4 == NUM8) || (PRM_4 == NUM16) || (PRM_4 == NUM32)) ; \
    Movlw INDEX_2 ; \
    #endif ; |
    #if((PRM_4 == BYTE) || (PRM_4 == WORD) || (PRM_4 == DWORD)) ; |
    #if(INDEX_2 <= BANKA_END) ; |
    Movfw INDEX_2 ; Get the second INDEX value into WREG
    #else ; |
    Movff INDEX_2,WREG ; |
    #endif ; /
    #endif ; /
    Addwf FSR0L,F ; \
    Movlw 0 ; Add this to FSR0
    Addwfc FSR0H,F ; /

    #if((PRM_3 == NUM8) || (PRM_3 == NUM16) || (PRM_3 == NUM32)) ; \
    Movlw INDEX_1 ; \
    #endif ; |
    #if((PRM_3 == BYTE) || (PRM_3 == WORD) || (PRM_3 == DWORD)) ; |
    #if(INDEX_1 <= BANKA_END) ; |
    Movfw INDEX_1 ; Get the first INDEX value into WREG
    #else ; |
    Movff INDEX_1,WREG ; |
    #endif ; /
    #endif ; /
    ENDASM-
    #if((PRM_2 != NUM8) && (PRM_2 != NUM16) && (PRM_2 != NUM32))
    #error "INDEX LENGTH must be a constant value for MARRAY_IN macro"
    #endif
    ASM-
    Mullw INDEX2_LENGTH ; \
    Movf PRODL,W ; \
    Addwf FSR0L,F ; Calculate the offset within the array
    Movf PRODH,W ; /
    Addwfc FSR0H,F ; /
    ;
    ; At this point FSR0 is pointing to the correct element based on INDEX_1, INDEX_2 and INDEX2_LENGTH
    ;
    #if(MARRAY_IN_RETURN == 1) ; Is there a return variable ?
    #if(RETURN_TYPE == BYTE) ; \
    Movff INDF0,RETURN_VAR ; \
    #endif ; |
    #if(RETURN_TYPE == WORD) ; |
    Byte_Word INDF0,RETURN_VAR ; Place the contents of the element into the return variable
    #endif ; |
    #if(RETURN_TYPE == DWORD) ; |
    Byte_Word INDF0,RETURN_VAR ; /
    #endif ; /
    #if(RETURN_TYPE == FLOAT)
    #error "Floating point not supported with the MARRAY_IN macro"
    #endif
    #endif
    ENDASM-
    ENDM
    '
    '-------------------------------------------------------------------
    ' The MAIN PROGRAM LOOP STARTS HERE
    ' Test the macros by loading then retieving values

    Delayms 100 ' Wait for things to stabilise
    Clear ' Clear all RAM before we start
    HSerout [" ARRAY CONTENTS",13,13]
    Hserout [" 00 01 02 03 04 05 06 07 08 09",13]
    Hserout [" -----------------------------",13]
    '
    ' Fill the 2 dimension array with values
    '
    For INDEX1 = 0 to DIMENSION_1 - 1 ' Create an outer loop for the first dimension
    Hserout [Dec2 INDEX1," | "]
    For INDEX2 = 0 to DIMENSION_2 - 1 ' Create an inner loop for the second dimension
    MARRAY_OUT XY_ARRAY,XY_ARRAY_LENGTH,[INDEX1,INDEX2], INDEX2 ' Fill array with value in INDEX2
    BYTE_OUT = MARRAY_IN XY_ARRAY,XY_ARRAY_LENGTH,[INDEX1,INDEX2] ' Read array value to BYTE_OUT
    Hserout [Hex2 BYTE_OUT,","] ' Display the value read from the array serially
    Next ' Close the inner loop
    Hserout [8,13] ' Send a Backspace and Carriage Return
    Next ' Close the outer loop
    Stop
    contributed by Les Johnson.
  • Recent Activity

    See_Mos-247

    Simple timer

    Thread Starter: amod

    Iam making a simple timer for 60 seconds with setpoint.suppose if I set 45 then timer start with a pulse and when I get 0 then timer stop. I tried...

    See_Mos Yesterday, 19:23 Go to last post