GPSIM en Ubuntu Natty

17 mei 2011

GPSIM is een simulator voor PIC microcontrollers. Link.

In de nieuwste release van Ubuntu is bij gpsim de GUI mogelijkheid uitgeschakeld. De reden daarvoor is dat een bibliotheek die deze tool voor de GUI gebruikt niet meer geleverd wordt door Ubuntu. Deze bibliotheek is: GtkExtra.

Dan maar zelf compileren.

  1. Eerst GtkExtra downloaden (versie 2.1.2)
  2. Installeer libgtk2.0-dev (extra afhankelijkheden worden automatisch geïnstalleerd):
    sudo apt-get install libgtk2.0-dev
  3. Pak de GtkExtra download uit.
  4. ./configure && make
  5. Error: ” gtkitementry.c:134:21: error: static declaration of ‘gtk_entry_reset_im_context’ follows non-static declaration”
  6. Bugje: Advies probeer de development versie.  Meerdere bugfixes, ook deze.
  7. Dan die maar downloaden: gtk+extra-3.0.1.tar.gz en uitpakken
  8. ./configure &&  make
  9. sudo make install
  10. Download gpsim: gpsim-0.26.1.tar.gz en uitpakken
  11. configure.ac aanpassen vanwege git+extra-3.0. Diff:
    --- configure.ac.orig   2011-05-17 11:59:41.634118818 +0200
    +++ configure.ac        2011-05-17 12:02:55.887734176 +0200
    @@ -79,15 +79,15 @@
     else
       dnl gtk2 checks
     
    -  $PKGCONFIG --exists gtkextra-2.0
    +  $PKGCONFIG --exists gtkextra-3.0
       if test $? != 0; then
    -    AC_MSG_ERROR(Cannot find gtkextra-2.0 package)
    +    AC_MSG_ERROR(Cannot find gtkextra-3.0 package)
       fi
     
       X_LDFLAGS=`$PKGCONFIG --libs gtk+-2.0 gthread-2.0`
       X_CFLAGS=`$PKGCONFIG --cflags gtk+-2.0`
    -  Y_LDFLAGS=`$PKGCONFIG --libs gtkextra-2.0`
    -  Y_CFLAGS=`$PKGCONFIG --cflags gtkextra-2.0`
    +  Y_LDFLAGS=`$PKGCONFIG --libs gtkextra-3.0`
    +  Y_CFLAGS=`$PKGCONFIG --cflags gtkextra-3.0`
       GTK_VERSION_T=`$PKGCONFIG --modversion gtk+-2.0`
       echo linking with gtk-$GTK_VERSION_T
       AC_DEFINE_UNQUOTED([GTK_VERSION],"$GTK_VERSION_T",[gtk version])
    
  12. autoconf
  13. ./configure
  14. sudo make install
  15. Enjoy!
screenshot

gpsim


Aansluiting display wekkerradio

2 september 2010

Om een oud display uit een defecte wekkerradio opnieuw te gebruiken heb ik de aansluitingen bepaald.

Code op de printplaat van het display “PC-1 94HB”. Dit schermpje zit wat vreemd in elkaar. Het is namelijk een display wat ooit door een LM8560 aangestuurd werd. Hergebruik met bv een PIC is helaas wat moeilijker.


Dobbelsteen

25 juni 2009


Deze elektronische dobbelsteen is een uitbreiding op de vorige post. De combinatie PIC en schuifregister wordt nu gebruikt om twee zeven segment displays aan te sturen. De displays worden gemultiplexed aangestuurd. Eerst de ene en daarna de andere. Dit wisselt zo snel dat het lijkt dat beide branden. Alle uit- en ingangen van deze kleine microcontroller worden gebruikt. 3 voor het aansturen van het schuifregister, twee voor het schakelen tussen de displays en een ingang voor de drukknop.

Het schema:

Schema dobbelsteen

Schema dobbelsteen

Het updaten van de displays gebeurt in een eindeloze lus. In pseudo-code:

loop:
shift data display 1
display 2 off
latch
display 1 on
shift data display 2
display 1 off
latch
display 2 on
goto loop

De data die verzorgt welke segmenten branden moeten, wordt uit een tabel gehaald via een computed goto.
Een 1 geeft aan dat het segment uit moet zijn, een 0 dat het segment moet branden. De index in deze tabel is het getal wat moet worden getoond.

seg_table
    addwf   PCL, f
    retlw   B'10001000'
    retlw   B'11011110'
    retlw   B'10100010'
    retlw   B'11000010'
    retlw   B'11010100'
    retlw   B'11000001'
    retlw   B'10000001'
    retlw   B'11011010'
    retlw   B'10000000'
    retlw   B'11000000'

Deze bitjes worden bepaalt door de manier het aansluiten van het display op de 74hc595. In volgende tekening zie je de manier die ik gebruikt heb. (Het was een vaag display wat ik ergens uit gesloopt heb. Common-anode, vandaar de aansturing van uit de +5V met een PNP transitor.)

dobbelsteen-7seg

dobbelsteen-7seg

Een gooi met de dobbelsteen wordt gedaan door op de drukknop te drukken. De waarde die op de displays wordt getoond moet natuurlijk willekeurig zijn. Deze willekeurigheid wordt bereikt door de onvoorspelbaarheid van het indrukken en loslaten van de knop. In de displaylus loopt een teller mee. Bij het indrukken van de drukknop wordt de waarde van de teller opgeslagen voor display 1 en bij het loslaten voor display 2. Deze worden vervolgens na loslaten getoond.

De asm-file: dobbelsteen.asm
De hex-file: dobbelsteen.hex


Shift register (74HC595)

24 mei 2009

Het aantal uitgangen van een PIC kun je bijna oneindig uitbreiden met een shift register. Dit projectje laat een 12F629 gekoppeld aan een 74HC595 zien. Het shift register laat acht LEDs oplichten.

Filmpje:

Het shift register is eenvoudig aan te sturen. De data wordt serieel in geklokt, na dat alle bits verzonden zijn, wordt via de latch klok de data op de 8 uitgangen gezet. De 74595 is aangesloten op de GP0, GP1 en GP2 aansluitingen van de PIC.

De shift_out routine:

DATAIN  equ GP2
SHIFT   equ GP1
LATCH   equ GP0
shift_out
    movwf tmp
    movlw 0x8
    movwf bits
loop1
    rlf tmp, f
    btfsc STATUS,C
    bsf GPIO, DATAIN
    btfss STATUS,C
    bcf GPIO, DATAIN
    nop
    bsf GPIO, SHIFT
    nop
    bcf GPIO, SHIFT
    decfsz bits, f
    goto loop1
    bsf GPIO, LATCH
    nop
    bcf GPIO, LATCH
    return

De data die de LEDs laat branden staat in code-memory en wordt uitgelezen via een computed-goto

data_array
    addwf PCL, f
    retlw B'00000000'
    retlw B'00000001'
    retlw B'00000010'
    retlw B'00000100'
    retlw B'00001000'
    retlw B'00010000'
    retlw B'00100000'
    retlw B'01000000'
    retlw B'10000000'
    retlw B'11111111'
    retlw B'00000000'
    retlw B'11111111'
    retlw B'00000000'
    retlw B'11111111'

Complete asm-file. Hex-file.

Schema:

Schema looplicht met 74595

Schema looplicht met 74595 (5V en Grond aansluitingen met ontkoppel-C's zijn weggelaten.)


Piklab, ICD2 debugger en programmer

18 mei 2009

Voor het programmeren van de PIC gebruik ik de Piklab IDE onder linux. Deze ondersteunt een aantal compilers, gputils voor het programmeren in assembler en een simulator. Ook ondersteund deze een aantal gangbare programmers.

De programmer die ik gebruik is een debugger/programmer. Het is een kloon van de ICD2 programmer van Microchip. Deze maakt gebruik van de originele Microchip firmware. Het is deze. Het debuggen heb ik niet geprobeerd. Ik heb niet de goede PIC’s omdat te proberen.

Het schema gebruikt in deze post:

pic629blink

Of als bestand te openen met gschem: pic629blink.sch

Een screenshot van het project geopend in Piklab:
piklab

Links zie je de bestanden die bij het project horen, instellingen voor het type PIC en een aantal debug vensters. In het midden worden de geopende bestanden getoond.

Voor het gebruik van de ICD2 programmer stel je Piklab in zoals in onderstaande screenshot:
piklab1
De ICD2 is nog niet aangesloten bij het maken van deze screenshot. Daardoor de connection: error. Bij het specific tabblad moet je de plek waar de firmware voor de programmer is opgeslagen aangeven. Ik heb MPLAB onder wine geïnstalleerd, dan wordt de firmware ook op de opgeslagen. Deze geef ik aan in de configuratie van Piklab.

Na het compileren kun je de PIC programmeren met het menu “Programmer”. Met dit menu kun je ook de PIC uitlezen. Bij het programmeren met de versie van Piklab die ik gebruik, crashed Piklab helaas.
ASSERT: "end<data.count()" in pic_prog_specific.cpp (35)
ASSERT: "mask" in pic_memory.cpp (287)
KCrash: Application 'piklab' crashing...

De workarround is het programmeren van de PIC via de commandline. Voor mijn programmer is het commando:

piklab-prog -c program -d 12f629 -p icd2 -t usb knipper-12f629-int-asm.hex

Dit werkt prima. Ook als de Piklab IDE zelf ook draait.

De asm-file en hex-file van het getoonde project in Piklab.


Looplicht 4

29 maart 2009

Looplicht 4 is een verbeterde variant van de voorgaande. Het dimmen van de leds is verwerkt in de hoofd PWM lus en verloopt nu veel vloeiender.

De code is wat ingewikkelder, voor het opschuiven van de leds wordt gebruik gemaakt van een computed-goto (berekende sprong) Dit maakt de code compact. Het dimmen is verstopt in een subroutine. Daar gebruik ik indirect adresseren om het dimmen van de leds in een lus te doen en het niet voor elke led te hoeven uitschrijven.

De hoofdlus bestaat uit twee geneste lussen. Een is de PWM lus. Binnen deze lus loopt een andere teller die af telt van 32. Als deze tellen 0 is worden de leds een stap gedimd. Het opschuiven gebeurt na dat de PWM lus 10 x 255 doorlopen is. Deze waarden zijn door te proberen bepaald. Zo vind ik het er het leukste uit zien.

Asmfile: looplicht4.asm
Hexfile: looplicht4.hex

; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

VAR     UDATA
led1    RES 1
led2    RES 1
led3    RES 1
led4    RES 1
led5    RES 1
led6    RES 1
led7    RES 1
led8    RES 1
ledH    RES 1
dir     RES 1
counter1 RES 1
counter2 RES 1
counter3 RES 1
output  RES 1
tmp     RES 1


; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    movlw   0
    movwf   TRISB
    bcf     STATUS, RP0
    
    movlw   0xff
    movwf   led1 
    clrf   led2
    clrf   led3
    clrf   led4
    clrf   led5
    clrf   led6
    clrf   led7
    clrf   led8
    clrf   ledH         ; Houdt bij welke led het felst brand.
    clrf   dir          ; Houdt de richting bij.
    movlw   1
    movwf   counter1
    movlw   0xa
    movwf   counter2
    movlw   0x20
    movwf   counter3
    
loop1
    movlw   0xff
    movwf   output
    movf    counter1, 0
    subwf   led1, 0
    btfss   STATUS, C    ;resultaat negatief -> counter > led1
    bcf     output, 0 
    movf    counter1, 0
    subwf   led2, 0
    btfss   STATUS, C
    bcf     output, 1
    movf    counter1, 0
    subwf   led3, 0
    btfss   STATUS, C
    bcf     output, 2
    movf    counter1, 0
    subwf   led4, 0
    btfss   STATUS, C
    bcf     output, 3
    movf    counter1, 0
    subwf   led5, 0
    btfss   STATUS, C
    bcf     output, 4
    movf    counter1, 0
    subwf   led6, 0
    btfss   STATUS, C
    bcf     output, 5
    movf    counter1, 0
    subwf   led7, 0
    btfss   STATUS, C
    bcf     output, 6
    movf    counter1, 0
    subwf   led8, 0
    btfss   STATUS, C
    bcf     output, 7
    movf    output, 0
    movwf   PORTB
    call    dim_leds
    incfsz  counter1
    goto    loop1
    incf    counter1            ; counter1 start bij 1
    decfsz  counter2
    goto    loop1
    movlw   0xa
    movwf   counter2
    movf    ledH, 0
    addwf   PCL, 1              ; computed goto, jump table
    goto    led1_high
    goto    led2_high
    goto    led3_high
    goto    led4_high
    goto    led5_high
    goto    led6_high
    goto    led7_high
    goto    led8_high
led1_high
    movlw   0xff
    movwf   led2
    incf    ledH
    goto    loop1
led2_high
    movlw   0xff
    btfss   dir, 0
    goto    led2_up
    movwf   led1
    decf    ledH
    bcf     dir, 0
    goto    loop1
led2_up
    movwf   led3
    incf    ledH
    goto    loop1
led3_high
    movlw   0xff
    btfss   dir, 0
    goto    led3_up
    movwf   led2
    decf    ledH
    goto    loop1
led3_up
    movwf   led4
    incf    ledH
    goto    loop1
led4_high
    movlw   0xff
    btfss   dir, 0
    goto    led4_up
    movwf   led3
    decf    ledH
    goto    loop1
led4_up
    movwf   led5
    incf    ledH
    goto    loop1
led5_high
    movlw   0xff
    btfss   dir, 0
    goto    led5_up
    movwf   led4
    decf    ledH
    goto    loop1
led5_up
    movwf   led6
    incf    ledH
    goto    loop1
led6_high
    movlw   0xff
    btfss   dir, 0
    goto    led6_up
    movwf   led5
    decf    ledH
    goto    loop1
led6_up
    movwf   led7
    incf    ledH
    goto    loop1
led7_high
    movlw   0xff
    btfss   dir, 0
    goto    led7_up
    movwf   led6
    decf    ledH
    goto    loop1
led7_up
    movwf   led8
    incf    ledH
    goto    loop1
led8_high
    movlw   0xff
    movwf   led7
    decf    ledH
    bsf     dir, 0
    goto    loop1
    
dim_leds
    decfsz  counter3
    return
    movlw   0x20
    movwf   counter3
    clrf   tmp
loop2
    movf    ledH, 0         ; tmp == ledH ?
    subwf   tmp, 0
    btfss   STATUS, Z
    goto    low1            ; no
    incf    tmp             ; yes
    goto    next
low1
    movlw   led1 
    addwf   tmp, 0
    movwf   FSR
    movf    INDF, 1
    btfss   STATUS,Z
    decf    INDF, 1
    incf    tmp
next
    movlw   0x8
    subwf   tmp, 0
    btfss   STATUS, Z
    goto    loop2
    return
END

Looplicht 3

29 maart 2009

Deze versie heeft een naijlend effect. Dit wordt bewerkt door de leds aan te sturen met een pulse-width-modulation (PWM) lus. In pseudo code voor een led:


teller = 1
ledwaarde = PWM-waarde
lus:
tmp-led = aan
als teller>ledwaarde
dan tmp-led = uit
led = tmp-led
goto lus

Dit is in de code 8 keer uitgeschreven.

Een variabele houdt de richting van het lopen bij. Elke 0xd (=14) keer de hoofdlus, schuift de felst brandde led een op. Van de andere wordt de waarde gehalveerd. Dit heeft een schoksgewijs dimmen van de leds tot gevolg. Het dimmen en opschuiven is ook 8 keer uitgeschreven.

Asmfile: looplicht3.asm
Hexfile: looplicht3.hex

; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

VAR     UDATA
led1    RES 1
led2    RES 1
led3    RES 1
led4    RES 1
led5    RES 1
led6    RES 1
led7    RES 1
led8    RES 1
dir     RES 1
counter1 RES 1
counter2 RES 1
output  RES 1



; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    movlw   0
    movwf   TRISB
    bcf     STATUS, RP0
    
    movlw   0xff
    movwf   led1
    clrf   led2
    clrf   led3
    clrf   led4
    clrf   led5
    clrf   led6
    clrf   led7
    clrf   led8
    clrf   dir
    movlw   1
    movwf   counter1        ; Counter start bij 1, 0 als ledwaarde is dan echt uit.
    movlw   0xd
    movwf   counter2
    
loop1
    movlw   0xff            ; PWM lus. Start met alle leds aan.
    movwf   output
    movf    counter1, 0
    subwf   led1, 0
    btfss   STATUS, C    ;resultaat negatief -> counter > led1
    bcf     output, 0       ; Dan led1 (=bit0) uit
    movf    counter1, 0
    subwf   led2, 0         ; Zelfde voor led2 en verder...
    btfss   STATUS, C
    bcf     output, 1
    movf    counter1, 0
    subwf   led3, 0
    btfss   STATUS, C
    bcf     output, 2
    movf    counter1, 0
    subwf   led4, 0
    btfss   STATUS, C
    bcf     output, 3
    movf    counter1, 0
    subwf   led5, 0
    btfss   STATUS, C
    bcf     output, 4
    movf    counter1, 0
    subwf   led6, 0
    btfss   STATUS, C
    bcf     output, 5
    movf    counter1, 0
    subwf   led7, 0
    btfss   STATUS, C
    bcf     output, 6
    movf    counter1, 0
    subwf   led8, 0
    btfss   STATUS, C
    bcf     output, 7
    movf    output, 0       ; output naar W register
    movwf   PORTB           ; W naar PORTB
    incfsz  counter1
    goto    loop1
    incf    counter1
    decfsz  counter2
    goto    loop1
    movlw   0xd
    movwf   counter2
    btfss   dir, 0              ; Richting omhoog of omlaag
    goto up
    goto down
up                              ; Uit geschreven elke ledbrandtijd is helft van vorige waarde.
    movf    led7, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led7_0xff        ; Led7 is vol aan
    goto    up_led7_div
up_led7_0xff                    ; Dan nu led8 vol aan
    movlw   0xff
    movwf   led8
    bsf     dir, 0
    goto up_next1
up_led7_div                     ; anders led8 halveren
    addlw   0                   ; Voor de zekerheid Carry = 0
    rrf     led8, 1
up_next1
    movf    led6, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led6_0xff
    goto    up_led6_div
up_led6_0xff
    movlw   0xff
    movwf   led7
    goto up_next2
up_led6_div
    addlw   0
    rrf     led7, 1
up_next2
    movf    led5, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led5_0xff
    goto    up_led5_div
up_led5_0xff
    movlw   0xff
    movwf   led6
    goto up_next3
up_led5_div
    addlw   0
    rrf     led6, 1
up_next3
    movf    led4, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led4_0xff
    goto    up_led4_div
up_led4_0xff
    movlw   0xff
    movwf   led5
    goto up_next4
up_led4_div
    addlw   0
    rrf     led5, 1
up_next4
    movf    led3, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led3_0xff
    goto    up_led3_div
up_led3_0xff
    movlw   0xff
    movwf   led4
    goto up_next5
up_led3_div
    addlw   0
    rrf     led4, 1
up_next5
    movf    led2, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led2_0xff
    goto    up_led2_div
up_led2_0xff
    movlw   0xff
    movwf   led3
    goto up_next6
up_led2_div
    addlw   0
    rrf     led3, 1
up_next6
    movf    led1, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led1_0xff
    goto    up_led1_div
up_led1_0xff
    movlw   0xff
    movwf   led2
    addlw   0
    rrf     led1, 1
    goto up_next7
up_led1_div
    addlw   0
    rrf     led2, 1
    addlw   0
    rrf     led1, 1
up_next7
    goto loop1
down
    movf    led2, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led2_0xff
    goto    down_led2_div
down_led2_0xff
    movlw   0xff
    movwf   led1
    bcf     dir, 0
    goto down_next1
down_led2_div
    addlw   0
    rrf     led1, 1
down_next1
    movf    led3, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led3_0xff
    goto    down_led3_div
down_led3_0xff
    movlw   0xff
    movwf   led2
    goto down_next2
down_led3_div
    addlw   0
    rrf     led2, 1
down_next2
    movf    led4, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led4_0xff
    goto    down_led4_div
down_led4_0xff
    movlw   0xff
    movwf   led3
    goto down_next3
down_led4_div
    addlw   0
    rrf     led3, 1
down_next3
    movf    led5, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led5_0xff
    goto    down_led5_div
down_led5_0xff
    movlw   0xff
    movwf   led4
    goto down_next4
down_led5_div
    addlw   0
    rrf     led4, 1
down_next4
    movf    led6, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led6_0xff
    goto    down_led6_div
down_led6_0xff
    movlw   0xff
    movwf   led5
    goto down_next5
down_led6_div
    addlw   0
    rrf     led5, 1
down_next5
    movf    led7, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led7_0xff
    goto    down_led7_div
down_led7_0xff
    movlw   0xff
    movwf   led6
    goto down_next6
down_led7_div
    addlw   0
    rrf     led6, 1
down_next6
    movf    led8, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led8_0xff
    goto    down_led8_div
down_led8_0xff
    movlw   0xff
    movwf   led7
    addlw   0
    rrf     led8, 1
    goto down_next7
down_led8_div
    addlw   0
    rrf     led7, 1
    addlw   0
    rrf     led8, 1
down_next7
    goto loop1
END