Search code examples
assemblymicroprocessors6502

Creating two square waves in assembly for the 6502


I am trying to generate two outputs: a 20Hz square wave and a 30Hz square wave in assembly using a 6502 micro controller instruction set. So far, I can output on 20Hz wave:

%uasm65,title="SQUARES"
    org 0200h
    lda #1d
    sta 0a200h
Main:
    ;jump to the subroutine Delay and do it
    jsr Delay
    lda 0a200h
    inc Count1
    lda Count1
    cmp #3d
    beq Reset1
    jmp Main

Reset1:
    lda #0d
    sta Count1
    lda 0a200h
    eor #00000001b
    sta 0a200h
    jmp Main

Reset2:
    jmp Main

Delay:
    ;Save registers on the stack.
    pha
    txa
    pha
    tya
    pha

;Change the number that is being loaded into the
; 'A' register in order to change the delay time.
    lda #01h

OutLoop:
    ldx #04h

InLoop1:
    ldy #0ffh

InLoop2:
    dey
    bne InLoop2

    dex
    bne InLoop1

    sec
    sbc #1d
    bne OutLoop

;Restore registers from the stack.
    pla
    tay
    pla
    tax
    pla

    rts

Count1:
    dbt 0d

Count2:
    dbt 0d

    end

%/uasm65

From my understanding, what I can do to accomplish this is to take a 60Hz square wave and use it to get a 30Hz and a 20Hz. How would output a 20Hz square wave to bit 5 of PortA and a 30Hz square wave to bit 6 of PortA without affecting the state of the other bits in the port? In other words, how do I get 20 and 30 from 60 here? Do I let the count check for 7 and increment count 2? any help would be greatly appreciated.


Solution

  • you need 2 separate counters, one for each pin

    Main:
        ;jump to the subroutine Delay and do it
        jsr Delay
        lda 0a200h      ; ?? what's this doing here?
    
        inc Count1   ; count1 is for the 20 Hz bit pin
        lda Count1
        cmp #3d       ; 60/20 = 3, so counter1 will have to reach 3
        bne Skip1     ; otherwise skip toggling
    toggle_pin5:
        lda #0d       ; reload first Counter
        sta Count1
        lda 0a200h
        eor #00000001b
        sta 0a200h
    skip1:
    
        inc Count2    ; count2 is for the 30 Hz bit pin
        lda Count2
        cmp #2d       ; 60/30 = 2, so counter2 will have to reach 2
        bne Skip2     ; you could also "bne Main" here
    toggle_pin6:
        lda #0d       ; reload 2nd Counter
        sta Count2
        lda 0a200h
        eor #00000010b ; you will want to change this for the correct value to "set bit6 of PortA"
        sta 0a200h
    
    skip2:
        jmp Main    
    
    Reset1:     ; not needed anymore
    Reset2:     ; not needed anymore
    
    Delay: [ ... ]
    

    Inside your loop, branching to Reset1 (or Reset2), and the jumping back to Main isn't such a good idea, you'd skip the 2nd check for the 2nd pin. Better just branch over the few instructions (as I did), or use a JSR/RET:

        cmp #3d
        bne SkipCall    ; counter value NOT reached, so skip "Reset"
        jsr Reset
    SkipCall:
        <...>
    
    Reset: 
        lda #0d
        sta Count1
        <...>
        ret