1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

PIC16F628A Rotate Left Thru Carry & Loop Around

Discussion in 'Microcontrollers' started by EvilGenius, Sep 25, 2014.

  1. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Hello
    I have been doing a lot of searches and study of codes and can't seem to find what I am looking for.
    I have two Ports (A & B). I want to be able to shift left from Port B thru carry and into Port A until data reaches A3.
    Once I shift left one more time, I like the data to loop back to B0 (the begining).
    I have seen setting up leftbit and rightbit and I know how to shift thru carry. If I shift left once again will the last bit (MSB) automatically fall into B0 (LSB)?

    Leftbit equ 3
    Rightbit equ 0
    clrf C
    set bits for port A and B
    rlf ....
     
  2. Mosaic

    Mosaic Well-Known Member

    Joined:
    Jun 3, 2010
    Messages:
    2,569
    Likes:
    128
    Location:
    Caribbean
    To begin, with the regular 16Fxxx series, you should use a shadow register for all PORT writes to avoid reading back incorrect pin values as caused by the read-modify-write behaviour of the ports.
    With the newer 16Fxxxx series and 18F you can rely on LATch instructions to sidestep RMW.

    So to answer your query as I understand it, you may need to add a delay loop if this is some sort of LED display:
    Code (text):
    ShadA equ 0x20
    ShadB equ 0x21
    Data     equ 0x22; keeps original dataset

    PORTSHIFT;
    movf Data,w; fetch original data
    movwf ShadB,w; update shadow register
    clrf ShadA

    call UPDATE; refresh PORTS
    rlf ShadB,f
    rlf ShadA,f; A0 = B7
    call UPDATE
    rlf ShadB,f
    rlf ShadA,f; A1 =B7, A0=b6
    call UPDATE
    rlf ShadB,f
    rlf ShadA,f; A2=B7,A1=B6,A0=B5
    call UPDATE
    rlf ShadB,f
    rlf ShadA,f; A3=B7,A2=B6,A1=B5, A0=B4
    call UPDATE
    return

    UPDATE; port refresh.
    movf ShadB,w
    movwf PORTB
    movf ShadA,w
    movwf PORTA
    clrc
    return
     
    • Like Like x 1
  3. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    You need to give some more details.

    Do you want to cyclycally rotate the same 12 bits of data through the PORTA[3..0] and PORTB[7..0] over and over again?

    Or do you want to read data from PORTB and then shift them bit by bit into PORTA[3..0]?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA

    Code (text):
    ;
    ;  12-bit ring counter spanning RA3..RA0..RB7..RB0
    ;
            clrc                    ; C = 0 (assume RA3 = 0)
            btfsc   PORTA,3         ; is RA3 = 0? yes, skip, else
            setc                    ; C = 1
            rlf     PORTB,F         ; shift lower 8 bits
            rlf     PORTA,W         ; shift upper 4 bits
            andlw   b'00001111'     ; just RA3..RA0 bits please
            movwf   PORTA           ; update PORTA

     
    Code (text):

    ;
    ;  12-bit ring counter spanning RA3..RA0..RB7..RB0
    ;  preserve RA7..RA4 bits
    ;
            clrc                    ; C = 0 (assume RA3 = 0)
            btfsc   PORTA,3         ; is RA3 = 0? yes, skip, else
            setc                    ; C = 1
            rlf     PORTB,F         ; shift lower 8 bits
            rlf     PORTA,W         ; shift upper 4 bits
            xorwf   PORTA,W         ; delta new & old bits
            andlw   b'00001111'     ; preserve RA7-RA4 bits
            xorwf   PORTA,F         ; update PORTA

     
     
    • Like Like x 1
  6. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Thank you for your responses.
    Here is in details what I am doing:
    Place value for A7,A6,A5,A4 (say 1101xxxx ) in a Variable called "Color" (to preserve the value)
    Place initial values in ValB and ValA (First 4-bit). Say A:xxxx1011 B:11001110
    Start Routine Here
    Rotate Left values of ValB and ValA (During rotate Left A3 drops into B0, B7 drops into A0)
    Add value of "Color" back into ValA
    Call Output (ValB-> PORTB, ValA->PORTA
    Loop the above routine 11 times so that at the end original B0 becomes A3, and original A3 become A2 (full rotate of 12 bits)

    In a sense we are preserving the values of 12 bits and rotating them after initializing them. Also preserving value of "Color" to be added on before sending it to output.
    Mike: You are very close to the concept. But what I am not seeing is moving A3 into B0 during rotate Left!
     
  7. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    I am thinking let A3 drop in A4, test A4 (set or not), accordingly set B0, then AND PortA with 00001111 as you suggested and save it back in PortA, add color and send it to Output. In a sense we are creating an artificial carry after A3 and using original Carry to transfer data from PortB to PortA.
     
  8. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    The first three instructions copy A3 into Carry before rotating PORTB. What are you "not seeing"?

    Code (text):
            clrc                    ; C = 0 (assume RA3 = 0)
            btfsc   PORTA,3         ; is RA3 = 0? yes, skip, else
            setc                    ; C = 1
            rlf     PORTB,F         ; shift lower 8 bits
     
    Perhaps you could simulate the code if it's unclear. Here's another way to do same thing;

    Code (text):
    ;
    ;  12-bit ring counter spanning RA3..RA0..RB7..RB0
    ;  preserve RA7..RA4 'color' bits
    ;
            swapf   PORTA,W         ; copy A3 bit to WREG bit 7
            addlw   0x80            ; copy it into Carry (C = A3)
            rlf     PORTB,F         ; shift lower 8 bits
            rlf     PORTA,W         ; shift upper 4 bits
            xorwf   PORTA,W         ; delta new & old bits, but,
            andlw   b'00001111'     ; preserve RA7-RA4 'color' bits
            xorwf   PORTA,F         ; update RA3..RA0 ring ctr bits

     
     
    Last edited: Sep 26, 2014
  9. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    ah-ha I think I see it now. So we are testing A3 first and setting Carry. At this point content of Carry is shifted into B0 as the result of first rlf-PortB and at the same time B7 drops into Carry. Now when we rotate PortA the new value of Carry (B7) drops into A0. By AND you get rid of rotated bit in A4. I see in your first code you moved the content of w into PortA which I get. Is this where you add "Color" to PortA. If so do I need another variable here so that content of PortA are preserved? What is the function of end xor?
     
  10. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    I just thought of something else. Do we need to worry about carry being cleared after rlf-PortA or will the second pass override it after testing for A3.
    To avoid another variable at the end, once we move w into PortA, add "color" to w (not PortA) and send it to Output from there.
     
  11. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    That code assumes "color" already occupies RA7..RA4 bit positions, thus the need to preserve RA7..RA4 bits when updating the ring counter RA3..RA0 bits.

    Do you need to preserve the contents of port A?

    The first XOR finds the differences between two values. The AND instruction filters out the bits that you don't want to change. The second XOR instruction writes the new A3..A0 values to PORTA. If PORTA contains color info in bits 7-4 and the four most significant bits of the 12-bit ring counter in bits 3-0, then you could use the routine I posted to advance the ring counter without disturbing the color bits. Likewise, when you want to update the four color bits without disturbing the four ring counter bits, you might use code like this;

    Code (text):

    ;
    ;  update four color bits in PORTA RA7..RA4
    ;  preserve ring counter bits in RA3..RA0
    ;
            movlw   b'10110000'     ; new color value
            xorwf   PORTA,W         ; delta new and old bits
            xorwf   PORTA,F         ; update RA7..RA4 color bits

     
    Take time to learn how to use the MPLAB Simulator and Watch Window to single step through code and see the results.

    Modify the code as necessary to support separate color and ring counter variables which can combined when needed for port updates.

    Cheerful regards, Mike
     
    Last edited: Sep 26, 2014
  12. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Code (text):
    Code (text):
     
    ;
    ;  12-bit ring counter spanning RA3..RA0..RB7..RB0
    ;
         cblock     0x20
                          copyPORTA
                          copyPORTB
                          Color
                          Count
         endc
    ;---------------------------------------------------------------
         movlw    b'11000000'        ;value for color
         movwf    Color
         movlw    b'10010001'         ;value for PortB
         movwf    copyPORTB
         movlw    b'00001001'         ;value for PortA
         movwf    copyPORTA
    ;--------------------------------------------------------------
    C0                                              
         movlw     d'11'
         movwf    Count
    C1
         clrc                                         ; C = 0 (assume RA3 = 0)
         btfsc        copyPORTA,3      ; is RA3 = 0? yes, skip, else
         setc                                        ; C = 1
         rlf             copyPORTB,F       ; shift lower 8 bits
         rlf             copyPORTA,W     ; shift upper 4 bits
         andlw      b'00001111'        ; just RA3..RA0 bits please
         movwf    copyPORTA          ; update PORTA
         addwf     Color, 0
         call          Output
         decfsz     Count
         goto        C1
         goto        C0
    ;----------------------------------------------------
    Output
         movwf    PORTA
         movfw    copyPORTB
         movwf    PORTB
         return  
     
     
  13. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Thanks for the example. It helps.
     
  14. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Mike do you see any problems with the code?
    If not, thank you for all your help.
    Cheers!
     
  15. NorthGuy

    NorthGuy Well-Known Member

    Joined:
    Sep 8, 2013
    Messages:
    1,218
    Likes:
    206
    Location:
    Northern Canada
    Is there some timing on this? In the original Mike's code there are 4 cycles between setting PORTA and PORTB, while in yours it's 2. Does this matter? How fast are you going to do this? Are you trying to do this as fast as possible? Or do you want some fixed intervals (delays?) between changes?
     
  16. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    I also wonder if speed is an issue since this seems to be some kind of LED code. If so, then should the ring counter bits be updated during a blanking interval (LEDs turned off)? Also, if speed is important than I would save four cycles by putting the output instructions in-line.

    Got a schematic so we can see what you're doin'?
     
  17. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    North: I need to do this as fast as possible. This is part of the engine for another program. In addition to copyPORTA and CopyPORTB, I will have 11 more set of 2 variables for total of 12 sets (of 2). The main program will set 12 colors for 12 RGB array. Each 12 sets of variables helps me create one frame of picture. Rotating the variables allows me to rotate all 12 colors across the 12 RGB LED's (12 Frames). There will not be a delay used in any part of the main program. To sustain colors each pass will modulate colors 60 times a second and each frame will be repeated 255 times a second to maintain all colors across 12 channels without flickering. The goal is to create a 12 channel RGB controller without use of PWM to achieve 33% duty cycle with much more vivid colors. 12 bits are your anodes while 3 color bits are your common R,G,B (12 Mux 3). The rotations happens between each frame so it has to be as fast as possible. In the example I am rotating 11 times rapidly, but in reality each rotate happens after each Frame is created so the timing between rotations is controlled by main program and is not like how it appears in the example in rapid succession.
     
  18. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Here is a schematic layout and color timeline.
     

    Attached Files:

  19. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    So you're trying to do software PWM for twelve RGB LEDs? If so, how many duty cycle steps per R, G, and B LED and what is the PWM period, please?

    <added>
    What are the bottom and right scales on your "color timeline", please?
     
    Last edited: Sep 26, 2014
  20. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    Just an FYI. I have written the functional code already, but it does not look pretty and is very repetetive. That is why I am redoing it to simplify it completely. So I know the concept works!
    Yes, it is software PWM. It is to take control of the timing and functions completely. This allows for much more control of brightness and also allows additional functions to be implemented as a stand-alone device. Believe it or not I have not sat down to calculate cycles. It has been by gutt feeling and trial & eror. I know to sustain colors I need to modulate each color minimum of 60Hz (my safe zone). But I am modulating much faster and refreshing much faster. Original code there are 12 frames. (not a timing consideration as I can speed up or slow down) Each Frame is looped 50 times. Each Frame calls on 3 sections (R,G,B color sets) and pushed them to Output. (7 instructions). each Section is looped 25 times, each loop has 10 instruction sets. So I would say total cycle time for one frame is: 50x3x25x10= 3750 cycles per second. The beauty is within the Frame which calls 3 Sections (R,G,B) so that I can get the maximum 33% duty cycle.
    Top: Your port assignment, Bottom is your time scale, right side is your y-axis scale (number of times each color is repeated). The idea is to run x-asix 252 to 0. Your y-axis will be how many times each section is repeated. To achieve Full Red you loop that section 84 times in B0 at x-axis=0 while the other two colors are zero. At x-axis=84 your red becomes zero, while your green peaks at 84, and blue is zero. Continue the logic for the other two points... Your x-axis is your main loop variable decrementing from 252 to 0. Within that loop you have a 3 train signals that have line forumlas for triangles. As you change x-axis, your y-values for each color changes incresing or decreasing intensity of each color (number of times it is looped). What you see in the graph is one entire frame. Rotate the variables where peaks and valleys are and repeate the same x-axis timeline and all your colors will rotate slightly. Do this over and over until your last frame will have the color red in it and then repeat the whole process.
    In this example since we are morphing from red to green to blue, my initial color sets are 0001xxxx, 0100xxxx, 1000xxxx. But you are not limited to these colors. You can set your initial colors to red (0001xxxx), yellow (0101xxxx), green (0100xxxx) and loop thru these colors only without use of blue. (xmas colors) and so on.....
     
    Last edited: Sep 26, 2014
  21. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    You lost me. I realize you'd like to move ahead on your project but I'd really like to figure out what you're doing. If you have time, could you tell me what is a "frame", please?

    Regards, Mike
     

Share This Page