;MACROS -------------------------------------------------------------------------- ; DecBufPtr <ptr> ; decrements buffer pointers and keeps them within one bank ; IncBufPtr <ptr> ; increments buffer pointers and keeps them within one bank ; mmov <src>,<dest>,<Count> ; Multi Move moves src to dest for count bytes. ; LookupW <12bitValue> [, <12bitValue>] ; uses IREAD (affecting M and W) to lookup values up to 12 bits indexed by W ; Subroutine ; Defines SubEntryAddr from the current address or the address of a jump from ; space in the first low half page of memory as needed to ensure global ; CALL access to a subroutine. ; Push, Pop ; compile code to push and pop W from a stack setup in one register bank. mmov Macro 3 local _bank noexpand _bank = 0 rept 3円 IF ((2円 + %) / 10ドル) != _bank _bank = (2円 + %) / 10ドル expand bank (2円 + %) noexpand ENDIF expand mov w, 2円 + % noexpand IF ((1円 + %) / 10ドル) != _bank _bank = (1円 + %) / 10ドル expand bank (1円 + %) noexpand ENDIF expand mov 1円 + %, w noexpand ENDR ENDM Push MACRO 1 local parm noexpand parm = 1円 expand DecBufPtr StackPtr ;could use incsz rather than inc to avoid modifying Z noexpand IF Parm == Wreg || parm == fsr IF parm != fsr expand mov fsr, w ;fsr could be anything (due to bank etc..) so use for parm noexpand parm = WReg ENDIF expand mov w, StackPtr ;get the StackPtr into w xor fsr, w ;swap w with fsr xor w, fsr xor fsr, w mov ind, w ;store w to Top Of Stack. noexpand ELSE expand mov fsr, StackPtr ;W used noexpand IF parm > 0ドルF expand bank parm mov w, parm bank Stack mov ind, w noexpand ELSE expand mov ind, parm noexpand ENDIF ENDIF ENDM Pop MACRO 1 noexpand expand mov fsr, StackPtr ;W used mov w, ind noexpand IF 1円 > 0ドルF expand bank 1円 noexpand ENDIF expand mov 1,円w ;1円 is now the StackPtr IncBufPtr StackPtr ;point to valid data at new Top Of Stack noexpand ENDM LookupW MACRO ;Version 2 local _LookupWTableBegin, _LookupWTableEnd, _temp expand ;Defines an in-line DW/IREAD lookup table returns the 12 bit value indexed by W in M:W. ;Affects M and W. noexpand if CPUCarry == 1 expand clc ;clc to avoid adding an extra one noexpand endif expand page $+0円+3 add w,2 ;add w,2 make the index into an offset from the current location jmp $+0円+1 noexpand _LookupWTableBegin = $ REPT 0円 expand DW \% noexpand ENDR _LookupWTableEnd = $ expand mov m,#_LookupWTableBegin>>8 noexpand IF (_LookupWTableBegin / 100ドル) != (_LookupWTableEnd / 100ドル) expand snc ;correct if carry due to table spanning a half page mov m,#_LookupWTableBegin>>8+1 noexpand ENDIF expand iread ;Retrieve data noexpand ;{use the data} ENDM ;============================== ;Ruben Jönsson ;AB Liros Electronic ;Box 9124, 200 39 Malmö, Sweden ;TEL INT +46 40142078 ;FAX INT +46 40947388 ;ruben@pp.sbbs.se ;============================== ; ;...a macro that will pack 3 ;characters at a time, from the string, into 2 program memory locations in ;order to save program memory. ; ;Since a program memory location can hold 12 bits it can store 1.5 ;characters if all 12 bits are used instead of using the RETLW instruction ;which only can store 8 bits. Of course, I have to use the IREAD instruction ;to read the characters. (The IREAD, by the way seems to have a problem when ;used on the SX52 (and probably the 48), but It's quite easy to make a fix ;for it.) ; ;I store the first character and the upper nibble of the third character in ;the first memory location and the second character and the lower nibble of ;the third character in the second memory location. The 3 characters 'ABC' ;would be stored as ; ;dw 441,ドル342ドル ;41,ドル42,ドル43ドル=ABC ; ;in 2 words of the 12 bit program memory. ; ;This is the (SASM) macro I use for this: ;-------------------------------------------------------------------------- ; Macro to pack 8 bit character strings into 12 bit program memory ; words. 3 character per 2 words of program memory. 1st memory ; location holds character 1 and upper nibble of character 3, 2nd ; memory location holds charachter 2 and lower nibble of character ; 3, 3rd location holds character 4 and upper nibble of character ; 6 and so on... ; If one string is split over several lines (several PackTXT macros) ; make sure that it is split on an even length of 3 characters. PackTXT MACRO LOCAL char1, char2 noexpand char1=-1 ;Temp variable for 1st character. char2=-1 ;Temp variable for 2nd character rept 0円 ;Repeat through all arguments to this ;macro (all characters). if ((%-1)//3 == 0) ;Is it charachter 1 (4, 7...)? char1=\% ;Save it for later endif if ((%-1)//3 == 1) ;Is it character 2 (5, 8...)? char2=\% ;Save it for later. endif if ((%-1)//3 == 2) ;If it is character 3 (6, 9...) we ;have a group of 3 characters to ;store 2 in memory words expand dw (((\% & $f0) << 4) + char1),(((\% & $f) << 8) + char2) noexpand char1=-1 char2=-1 endif endr if char1 != -1 ;If the number of characters are 1 or 2 ;(4,5,7,8....) store character 1 (4,7...) ;in a single word expand dw char1 noexpand endif if char2 != -1 ;If the number of characters are 2 (5,8...) ;store character 2 (5,8...) in a single word. expand dw char2 noexpand endif endm ;With the Parallax assembler I can just write ; ; PackTXT 'ABCDEFG' ; ;But the SASM assembler requires me to write ; ; PackTXT 'A','B','C','D','E','F','G' ;Here is the code I have used for reading back my packed ;strings. It could probably be more generalized regarding ;register usage, but this is how it is done in my application. ; ;It uses two global registers, TMP1 and TMP3, and 2 non global ;registers MEM_PTR_L and CHAR3. It takes an offset to the first ;character in the string in a string table as input in W. This ;function is optimized for a string table of up to 256 program ;words - up to 384 characters (384 is 256 * 1.5 but this ;requires all strings to be of a length even divisible by 3 - ;which most likely isn't the case, making the maximum number of ;characters somewhat less than 384). This routine also requires ;all strings to be in the same 256 byte (half) page. I have used ;a constant, LCD_END_STR, instead of 0 as an end marker for the ;strings since I also need to send the character 0 (user defined ;character and definition of this to an LCD). ; ;string_to_lcd_buff ; bank MEM_PTR_L ; mov MEM_PTR_L,w ;Offset in string table ; clr TMP3 ;Byte read counter ;string_to_lcd_buff_loop ; mov m,#(rom_strings>>8);High nibble offset ; mov w,MEM_PTR_L ; iread ;Read character ; inc TMP3 ;Inc byte read counter ;string_to_lcd_buff_001 ; mov TMP1,w ;Save read byte. ; xor w,#LCD_END_STR ;Is it the end of the ;string? ; snz ; retp ;Yes - exit ; swap CHAR3 ;Make the 3rd character from ; ;The two previously read ; mov w,#$f0 ;Mask off the lower nibble ; and CHAR3,w ; mov w,m ; and w,#$f ;Add the high order nibble ; ;from this IREAD. ; or CHAR3,w ; call @putchar_lcd+1 ;Sends TMP1 to LCD buff ; sb TMP3.1 ;Is 2 bytes read? ; jmp not_third_char ;No - continue with next ;char ; clr TMP3 ;Yes - clear counter and ; mov w,CHAR3 ;send the char in CHAR3 ; jmp string_to_lcd_buff_001 ;not_third_char ; inc MEM_PTR_L ;Increment pointer to next ; ;memory location. ; jmp string_to_lcd_buff_loop ; Subroutine MACRO noexpand ;Usage: Define a Global lable, ; Execute Subroutine macro, ; Assign :Entry to the value now set in SubEntryAddr. ; Continue the definition of the subroutine. ; Elsewhere, call @Sub:Entry where Sub is the global lable ; you defined for the subroutine. ;Example ;SUB1 Subroutine ;:Entry = SubEntryAddr ;.... ; Call SUB1:Entry _SubAddr = $ IF (_SubAddr & 100ドル) != 0 org LowHalfPage SubEntryAddr = $ ;if we got here, the pagesel bits must be set for here IF ($ / 100ドル) == (_SubAddr / 100ドル) expand jmp _SubAddr noexpand ELSE expand jmp @_SubAddr noexpand ENDIF LowHalfPage = $ IF $+1 > HighHalfPage ERROR 'Out of LowHalfPage Space' ENDIF org _SubAddr ELSE ;The subroutine was already starting in a LowHalfPage SubEntryAddr = $ ENDIF ENDM DecBufPtr MACRO 1 noexpand ;decrements buffer pointers and keeps them within one bank IF CPUPins > 28 expand dec 1円 setb 1円.5 noexpand ELSE expand dec 1円 setb 1円.4 noexpand ENDIF ENDM IncBufPtr MACRO 1 noexpand ;increments buffer pointers and keeps them within one bank IF CPUPins > 28 expand inc 1円 setb 1円.5 noexpand ELSE expand inc 1円 setb 1円.4 clrb 1円.5 noexpand ENDIF ENDM Inc24 MACRO 1 inc 1円+0 snz inc 1円+1 snz inc 1円+2 ENDM
.