; Test of various jump table options ; ; Jump tables can be ; a. In the first 256 bytes of the same page as the call ; b. Not in the same page as the call. This can also include a,c,d or e. ; c. Not in the first 256 bytes of a page ; d. Spanning the 256 byte boundary or a page boundary (most general case) ; e. Larger than 256 bytes (the general case plus two long for a normal jump) ; ; This program has one of each type with the output going to the led_bar for the ; sake of convenience. ; ; In addition, call and goto instructions can be within a page or can reference ; another page. Just to cram everything in one place, this also has inter-page jump ; and call situations. LIST P=16F877, R=DEC INCLUDE "C:\MPLAB\P16F877.inc" ; Definitions ; __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC ; Define start of vars ; This is the far call macro for calling into other pages. The call instruction ; can address 11 bits, so all we have to do is worry about the upper two bits ; of PCLATH. Get those from the label and set before doing the call. The return ; is 13 bits, so it will get back here, and then reset PCLATH for the original page farcall macro flabel LOCAL mask, cpage ; Create the mask for the page bits movlw HIGH $ & 0x18 movwf mask movlw HIGH flabel & 0x18 iorwf mask,F movf mask,W xorwf HIGH flabel,W movwf PCLATH call flabel & 0x07FF ; return comes to here. We need to restore the proper page bits for original call ; xorwf endm ScratchPad EQU 0x20 ; Variables Temp EQU ScratchPad+1 Counter EQU ScratchPad+2 BigTableOff EQU ScratchPad+3 ; high-order byte of two byte offset for BigTable mS_0 EQU ScratchPad+5 mS_1 EQU ScratchPad+6 FarParam EQU ScratchPad+7 ; needed for far table ; Start of the Program ORG 3 goto Start ; This code reads the dip switch and stores the bit pattern in Dippy and then outputs ; to the led_bar. ; ORG 0x20 NearTable ; This is case a, table in first 256 bytes addwf PCL,F retlw b'00000001' retlw b'00000011' retlw b'00000010' retlw b'00000100' retlw b'00000101' NearTableEnd ; This is a case e, a table that is bigger than 256 bytes. Its also outside of the first ; 256 bytes, but each case will be handled independently. org 0x100 BigTable movlw HIGH BigTableBegin addwf BigTableOff,W movwf PCLATH movlw BigTableBegin & 0x0FF addwf BigTableOff+1,W btfsc STATUS,C incf PCLATH,F movwf PCL BigTableBegin dt "Fourscore and seven years ago our forefather brought forth upon this" dt "continent, a new nation, conceived in liberty, and dedicated to the" dt "proposition, that all men are created equal. Now we are engaged in a" dt "great civil war, testing whether that nation, or any nation, so" dt "conceived and so dedicated can long endure." Start ; Set up RC3 to be output, RB3 to be input, A4-A0 to be output. bsf STATUS, RP0 clrf TRISA clrf TRISD ; to use the led_bar for output bcf STATUS, RP0 MainLoop ; First, access the NearTable and output the results movlw 3 ; should be 0000 0100 call NearTable call DispLedBar movlw 250 ; About a 1 second delay call Delay ; Access the BigTable and output the results movlw 1 movwf BigTableOff ; High order of 264- should be 's' (01110011) movlw 8 movwf BigTableOff + 1 ; Low order of 264 call BigTable call DispLedBar movlw 250 ; About a 1 second delay call Delay ; Access the NotNearTable movlw 3 ; should be 0000 1011 call NotNearTable call DispLedBar movlw 250 ; About a 1 second delay call Delay ; Access the Split Table movlw 8 ; should be 00111010 call SplitTable call DispLedBar movlw 250 ; About a 1 second delay call Delay ; Access the FarTable ; This requires a special call (goto's are the similar but not identical) to make sure ; that the page bits are properly loaded. TempLabel movlw 3 ; will return 11001011 movwf FarParam farcall FarTable call DispLedBar movlw 250 ; About a 1 second delay call Delay ; Access the FarRoutine ; movlw 3 ; farcall FarCode ; will return 1111 1111 ; call DispLedBar ; movlw 250 ; About a 1 second delay ; call Delay goto MainLoop ; Subroutine to display W on the led bar DispLedBar ; Enable the led bar and put the value in W there. movwf Temp ; save W movlw 0x12 movwf PORTA comf Temp,W movwf PORTD return Delay ; ---------------------------------------------------------------- ; Routine to dealy a specified number of miliseconds ; inputs - milliseconds to Delay (w), outputs - none ; ------------------------------------------------------------------ mS_Delay movwf mS_0 mS_loop_0 ; outer delay loop movlw 250 movwf mS_1 mS_loop_1 ; inner delay loop fill (nop), 68 ; Note change from original version decfsz mS_1,F goto mS_loop_1 clrwdt decfsz mS_0,F goto mS_loop_0 return ; This table is org'd to be beyond 256 bytes org 0x300 ; at location 756 in first page NotNearTable ; case c, not in first 256 bytes movwf Temp ; save the offset movlw HIGH $ ; Get the current page high order bits movwf PCLATH ; and save it movf Temp,W addwf PCL,F dt b'00001000',b'00001001',b'00001010',b'00001011',b'0001100',b'00001101' ; Org to insure that the table spans a 256 byte boundary. This code will work for ; any table, regardless of where it is. org 0x3F2 SplitTable ; case d, table spans a page boundary (or 256 byte boundary) movwf Temp movlw High SplitTabBegin movwf PCLATH movf Temp,w addlw LOW SplitTabBegin btfsc STATUS,C incf PCLATH,F movwf PCL ; First 5 are in page 1, second are in page 2 SplitTabBegin dt b'00011000',b'00011001',b'00011010',b'00011011',b'0011100',b'00011101' dt b'00111000',b'00111001',b'00111010',b'00111011',b'0111100',b'00111101' ; ================================================================================== ; This is in a different page ; Page1 org 0x0800 FarTable ; case b, in a different page, but in first 256 bytes movlw HIGH $ ; Get the current page high order bits movwf PCLATH ; and save it movf FarParam,W addwf PCL,F dt b'11001000',b'11001001',b'11001010',b'11001011',b'1101100',b'11001101' ; Here is subroutine in Page 1 FarCode movlw b'11111111' return ; Wait forever Forever waitforever nop goto waitforever return END