'
' 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
' 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


Menu
Recent Articles


Using PDS with SPI GLCD based on ST7565R Controller
Graphic LCDs based on the ST7565 are cheaper then GLCDs with other controllers. SPI requires only four pins. If the circuit