Using an Assmbly Routine in PBP


+ Reply to Thread
Results 1 to 8 of 8
  1. #1
    Join Date
    Jun 2005
    Posts
    20

    Default Using an Assmbly Routine in PBP

    Hi--

    I'm trying to adapt Microchip's AN1076 appnote on DMX to use as an assembly language subroutine in PBP. I'm using a PIC18F4520, 16MHz resonator, PBP 2.5a. What the code should do is initialize the LCD, read the DMX data stream, and then display the value present on DMX channel 7 on the LCD. I am feeding in a DMX signal, and I've had a PBP-coded subroutine working just fine on my hardware test board, but I need more speed. Both the SetupSerial subroutine and the DMXloop subroutine compile just fine, but when I call the DMXloop subroutine, that's the last I see of my program's execution, nothing else happens. I assume I'm jumping off into oblivion somehow... my understanding of assembly is limited, so I'd appreciate any commentary.

    Thanks in advance--

    --Alan

    Code:
        ' for PIC18F4530
    	DEFINE OSC 16   
    	INCLUDE "modedefs.bas"
    	include "LCD_defines602.pbp"
    	  
    '  ****************************************
    '  SETUP 
    '  ****************************************	
    	
    	PORTA = %00000000
    	PORTB = %00000000
    	PORTC = %00000000
    	PORTD = %00000000
        trisa = %11111101
        trisb = %01111111
        TRISC = %11101000
        trisd = %11001011
    	
    	ADCON1 = %00001111					'port a is all digital IO
    	CMCON = 7                           'and turn off those pesky comparators
    	RBPUx			VAR	INTCON2.7	    'port b pull-ups 1 = disabled 0 = enabled
    	RBPUx = 0
    	trise.4 =%0                         'disable PSP port
        	
    ' ===================================
    ' define hardware pins:
    ' ===================================
    	
    	BKLT            var portd.5         'LCD backlight
        
    ' ================================	
    '	define constants & variables:
    ' ================================
    
        DMXrxbuffer     var byte[512]
        CountH          var byte
        CountL          var byte
        count0          var byte
    
        
    '  ****************************************
    '  INITIALIZATION
    '  ****************************************
    init:
            call SetupSerial    'set up USART and clear DMXrxbuffer
            
    '  ****************************************
    '  MAIN LOOP
    '  ****************************************
    
    begin:	low bklt                        'turn on backlight
            pause 125                       'pause to let LCD initialize
            lcdout $fe,1                    'clear screen        
            LCDout "  test routine   "       'display splashscreen
            lcdout $fe,$c0,"S/W Version 6xxx"
            pause 1200
    
    
    low bklt
    
    mainloop:
    
    
        Call DMXloop
        lcdout $fe,1
        pause 3
        lcdout dec DMXrxbuffer[7]
        pause 300
        
    goto mainloop
    
    
    asm
    
    _DMXloop
    	
    ; first loop, synchronizing with the transmitter
    _WaitBreak
    	btfsc	PIR1,RCIF           ; if a byte is received correctly
    	movf	RCREG,W             ; discard it
    	btfss	RCSTA,FERR			; else 
    	bra		_WaitBreak          ; continue waiting until a frame error is detected
    	movf	RCREG,W				; read the Receive buffer to clear the error condition
    
    ; second loop, waiting for the START code
    _WaitForStart
    	btfss	PIR1,RCIF			; wait until a byte is correctly received
    	bra		_WaitForStart
    	btfsc	RCSTA,FERR
    	bra		_WaitForStart
    	movf	RCREG,W	
    
    ; check for the START code value, if it is not 0, ignore the rest of the frame
        andlw   0xff
        bnz     _DMXloop             ; ignore the rest of the frame if not zero 
    
    ; init receive counter and buffer pointer        
        clrf    _CountL
        clrf    _CountH
        lfsr    0,_DMXrxbuffer
    
    ; third loop, receiving 512 bytes of data
    _WaitForData
        btfsc   RCSTA,FERR          ; if a new framing error is detected (error or short frame)
        bra     _RXend              ; the rest of the frame is ignored and a new synchronization
        							; is attempted
    
    	btfss	PIR1,RCIF			; wait until a byte is correctly received
    	bra		_WaitForData	    ;
    	movf	RCREG,W				; 
    
    _MoveData
    	movwf	POSTINC0			; move the received data to the buffer 
                                    ; (auto-incrementing pointer)
    	incf	_CountL,F           ; increment 16-bit counter
    	btfss	STATUS,C
    	bra		_WaitForData
    	incf	_CountH,F
    
    	btfss	_CountH,1            ; check if 512 bytes of data received
    	bra		_WaitForData
    
    _RXend	
    	return
    
    ;****************************************************************
    
    ; Setup Serial port and buffers
    _SetupSerial
    
    ;Clear the receive buffer
    	lfsr	0,_DMXrxbuffer
    _CBloop
    	clrf	POSTINC0	    ; clear INDF register then increment pointer
    	incf	_CountL,F
    	btfss	STATUS,C
    	bra		_CBloop
    	incf	_CountH,F
    
    	btfss	_CountH,1
    	bra		_CBloop	
    
    ; Setup EUSART
    	bsf		TRISC,7         ; allow the EUSART RX to control pin RC7
    	bsf		TRISC,6         ; allow the EUSART TX to control pin RC6
    
    	movlw	0x04			; Disable transmission
    	movwf	TXSTA			; enable transmission and CLEAR high baud rate
    
    	movlw	0x90
    	movwf	RCSTA			; enable serial port and reception
    
    	bsf		BAUDCON,BRG16	; Enable UART for 16-bit Asyn operation
    	clrf	SPBRGH
    
    	movlw	.15				; Baud rate is 250KHz for 16MHz Osc. freq.
    	movwf	SPBRG	
    
    	return
    
    endasm
    Last edited by alanmcf; - 1st August 2008 at 02:27.

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    Well, I can't see anything wrong with the ASM part. It compiles, and looks like it should work. But there are a couple possibilities ....

    If you are expecting to receive data from DMX channel 7, it will be in DMXrxbuffer[6], since the first "Device ID" byte (always 0) is discarded.

    And, 250k baud is pretty fast for a resonator. You might want to try a crystal with caps.
    <br>
    DT

  3. #3
    Join Date
    Jun 2005
    Posts
    20

    Default

    Hi Darrel--

    Right on about the channel, it should say 6. Otherwise, I don't think it's a hardware issue, i.e. resonator vs. crystal... I've been using PBP code (follows) to capture a single channel or two and it works great, but I'd like to get the whole 512 channels, hence trying to adapt AN1075. I think its getting lost somewhere... could this have something to do with BANK0, BANK1, etc?

    This is the PBP routine that I have been using to read 2-3 channels at a time; on this same hardware platform it works great...

    Code:
     '====================================================
    ' DMX Subroutines
    '====================================================    
    
    readdmx:
            counter = 1
           	PIE1 = 0				' Mask the interrupt
            pulsin target, 0, counter
            idleflag = 0
            DMX_OK = 1
            if counter = 0 then
                idleflag = 1                        'either no DMX or break timed out
                DMX_OK = 0                          'set DMX as not present
                goto noshow_exit
            endif
            
            if counter < 35 then readDMX            'active pulse too short, keep looking
                                  'otherwise its valid DMX & time to read the start code
            dummy = rcreg
            dummy = rcreg 'do this twice to clear out ang garbage in the USART
            spbrg = 0
            txsta.2 = 0 'brgh = 0
            txsta.4 = 0
            rcsta.7 = 1 'turn on the USART
            rcsta.6 = 0 'setting 8 bit receive mode, no parity, etc.
            rcsta.4 = 0
            rcsta.4 = 1 'toggle the rcsta.4 bit to make-ready
            
            while rcif = 0 : wend   'hover until start code is received
            
            startcode = rcreg 'read the startcode somewhere, tho most likely we'll never look at it
    
            if dmx_channel = 1 then  'if DMX address is 1, do this special case
                dummy = rcreg
                goto exit_readDMX
            endif        
            
            'else, do this code for DMX addresses 2-512:        
            count0 = 0       
            While count0 < (dmx_channel-1) 'set up loop to count up to just 1 shy of target address
                while rcif = 0 : wend   'wait for a byte
                dummy = rcreg
                count0 = count0 + 1           
            WEND        
        exit_readDMX:   
            DMX_data = rcreg         'put the DMX byte into a variable and exit
        noshow_exit:
            rcsta.7 = 0              'turn off the USART
            if intensity > 0 then
                PIE1 = 1                        'restore interrupt
            else
                PIE1 = 0                        'if the intensity is >0, let the elapsed timer run
            endif
        return

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    Quote Originally Posted by alanmcf View Post
    ... could this have something to do with BANK0, BANK1, etc?
    On an 18F, banking problems don't show up till you have more than ~200 bytes worth of variables.... You have 3. Not including the array, which is handled nicely by the FSR0 indirect.

    One thing your PBP version has, that the ASM doesn't, is clearing an OERR condition (CREN toggle).

    OERR locks up the USART until cleared, and many bytes could be received before the program looks for data. So it's probably overflowed before it gets to the ASM routine.
    <br>
    DT

  5. #5
    Join Date
    Mar 2006
    Posts
    41

    Talking

    Quote Originally Posted by Darrel Taylor View Post
    On an 18F, banking problems don't show up till you have more than ~200 bytes worth of variables.... You have 3. Not including the array, which is handled nicely by the FSR0 indirect.

    One thing your PBP version has, that the ASM doesn't, is clearing an OERR condition (CREN toggle).

    OERR locks up the USART until cleared, and many bytes could be received before the program looks for data. So it's probably overflowed before it gets to the ASM routine.
    <br>

    Sir Darrel;
    I'd like to ask which would you most prefer and or convenient with PIC18F data ram addressing "Access Ram" or "Indirect Addressing"

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    Quote Originally Posted by leisryan View Post
    I'd like to ask which would you most prefer and or convenient with PIC18F data ram addressing "Access Ram" or "Indirect Addressing"
    They're really two completely different things.
    But if I had to choose one, I'd say "Indirect Addressing".

    Access Ram is more for optimizing the code, reducing the size by letting you do things with less bank switching. It doesn't really give any additional functionality.

    But "Indirect Addressing" let's you use the entire RAM space like it's a big array, which adds just a TON of functionality. Strings, packets, buffers, software stacks, etc. etc.
    <br>
    DT

  7. #7
    Join Date
    Mar 2006
    Posts
    41

    Smile

    Quote Originally Posted by Darrel Taylor View Post
    They're really two completely different things.
    But if I had to choose one, I'd say "Indirect Addressing".

    Access Ram is more for optimizing the code, reducing the size by letting you do things with less bank switching. It doesn't really give any additional functionality.

    But "Indirect Addressing" let's you use the entire RAM space like it's a big array, which adds just a TON of functionality. Strings, packets, buffers, software stacks, etc. etc.
    <br>
    Wow!!! I really appreciate it really enlightening!!! Is bank switching still occurs in "Indirect Addressing" Un-noticeably though?
    Last edited by leisryan; - 5th September 2008 at 01:29.

  8. #8
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    > Is bank switching still occurs in "Indirect Addressing" Un-noticeably though?

    Well, YES and NO.

    But, if I had to choose one ...
    I'd say NO.

    On 18F's, the FSRx registers are 12-bits wide.
    Which means it can address any location from 0 to 4095 ($000 to $FFF).
    It can access memory locations in ANY BANK without having to change the current bank (BSR). It's just a single address.

    The beauty of this, is that no matter what bank your program is currently using, you can read/write from any other bank without switching the banks back and forth. Which may be where your original question was aimed, because Indirect addressing can be a good tool for optimization, much like the Access RAM.
    DT

Similar Threads

  1. PBP Book
    By Bruce in forum Off Topic
    Replies: 83
    Last Post: - 4th October 2021, 13:55
  2. PBP, ASM and LST files
    By HenrikOlsson in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 12th January 2010, 14:43
  3. Compiler differences between PBP 2.33 & 2.46
    By nikopolis in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 2nd May 2006, 20:01
  4. Newby- PBP wont compile for 18F (MPLAB)
    By jd76duke in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 18th December 2005, 00:30
  5. Replies: 2
    Last Post: - 8th August 2004, 17:00

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts