Audio Control with a Pic16F887 and PGA2310

Thread Starter

James Harris 2

Joined Aug 22, 2017
7
How everyone I am working on a project for school a audio amplifier to be exact. I have to use the Pic16F887 in the build, the PGA2310 while i have already brought that part. Anyways the project most be coded in Assembly Language
 

Thread Starter

James Harris 2

Joined Aug 22, 2017
7
How everyone I am working on a project for school a audio amplifier to be exact. I have to use the Pic16F887 in the build, the PGA2310 while i have already brought that part. Anyways the project most be coded in Assembly Language. Sorry the code is below it has an rotary encoder controlling the volume then a button press causes it to control balance. The balance is tested to see if the rotate should result in an addition to the right channel if CW movement or a subtraction of the left channel, inverse if the movement is CCW. Just waited to know if anybody sees a way i can reduce length sadly it as to be in Assembly.

Code:
[Name: PicLab9.asm
; By James Harris

    __config    _CONFIG1,            0x03F4        ; internal oscillator, WDT off
    __config    _CONFIG2,            0x3FFF
    #include    p16f887.inc                            ; included with MPLab
    #include    lowercase_887sfr.inc            ; in the Files folder (see note)

;define variables
cblock 0x20
direction,
w_save,
status_save,
pclath_save,
m_index,
volume_data,
volume,
userflags,
volume_Right,
Right_Channel,
volume_Left,
Left_Channel
endc

;define constants
    #define    DRE_0                portd,3
    #define    DRE_1                portb,1
    #define    Left                 userflags,0
    #define    Right                userflags,1
    #define    Unbalance            userflags,2
    #define    CW_Rotate            userflags,3
    #define    Gain_on_Left         userflags,4
    #define    Gain_on_Right        userflags,5

    org        0x00
    call    Init
    goto    Main

    org    0x04                        ; interrupt vector
    movwf    w_save                  ; save registers
    swapf    status,W
    movwf    status_save
    movf    pclath,W
    movwf    pclath_save
    clrf    pclath
    call    Isr
    movf    pclath_save,W            ; restore registers
    movwf    pclath
    swapf    status_save,W
    movwf    status
    swapf    w_save,F
    swapf    w_save,W
    retfie

Volume_table
    movf    volume, W                ; add index to pcl
    andlw    b'00011111'                ; mask numbers larger then 31
    addwf    pcl, F
    dt        .0,.1,.63,.73,.83,.93,.103,.113,.123,.133,.143,.153,.163,.173,.183,.192,.193,.194,.195,.196,.197,.198,.199,.200,.201,.202,.203,.204,.205,.206,.207,.208

Init
    bsf        status,RP0                ;switch to Bank1
    bsf        pie1,SSPIE
    clrf    SSPSTAT
    bsf        sspstat,CKE
    bsf        trisb,1
    bcf        trisc,3
    bcf        trisc,5
    bcf        trisd,2
    bsf        trisd,3
    bsf        trisd,4
    banksel    anselh
    bcf        anselh,ANS10                ;enable digital input on RB1
    banksel    option_reg
    bcf        option_reg,NOT_RBPU      ;enable pull-ups
    banksel    wpub
    bsf        wpub,WPUB1               ;enable RB1 pull-up
    banksel    iocb
    bsf        iocb,IOCB1               ;enable RB1 on-change interrupt
    bcf        status,RP0
    movlw    b'01110010'                ;8MHz internal oscillator???
    movwf    osccon                        ;osccon is in bank1
    bcf        status,RP0               ;switch to Bank0
    movlw    b'00100010'
    movwf    sspcon
    bcf        portc,5
    bcf        portc,3
    bsf        portd,2
    clrf    volume
    clrf    direction
    clrf    sspbuf
    clrf    userflags
    clrf    volume_Right
    clrf    volume_Left
    clrf    Right_Channel
    clrf    Left_Channel
    bsf        intcon,RBIE              ;enable interrupts
    bsf        intcon,PEIE
    bsf        intcon, GIE
    return


Main
    goto    Main

Isr
    btfss    intcon,RBIF
    return
    call    Dre_isr
    return

Dre_isr
    movf     portb,W               ;ends the mismatch on change
    bcf      intcon,RBIF           ; clear portb interrupt flag
    btfss    DRE_0                 ; detect direction
    return                         ; negative edge only
    movlw    1                     ; CW
    btfss    DRE_1
    movlw    -1                    ; CCW
    movwf    direction
    btfss    portd,4               ; Test if Balance Button Pressed
    call     Volume_isr
    btfsc    portd,4               ; Test if in Balance mode
    call     Unbalance_isr
    clrf     direction             ; Clear direction data for next cycle
    return                    
Volume_isr
    movf     direction,W          ; place direction value in working register to add to volume total
    addwf    volume,F
    call     Volume_table         ; fetch PGA2310  binary volume equivalent
    movwf    volume_data            ; store the volume information
    movf     volume_data,W        ; move volume information into the Working Register
    call     Transmit
    movf     volume_data,W        ; Move volume_data into Left,Right Volume register used as reference
    movwf    volume_Left
    movwf    volume_Right
    clrf     Right_Channel        ; Clear Channels for balance change reference point
    clrf     Left_Channel
    return

Unbalance_isr
    comf     direction,W          ; If the Z flag is set then the direction was CCW
    btfss    status,Z
    call     Right_CW
    btfss    CW_Rotate            ; Set CW_Rotate when enter Right_CW to skip Left_CCW on return
    call     Left_CCW
    bcf      CW_Rotate        
    return

Right_CW
    movf     Left_Channel         ; Move Left_Channel so no increment occurs on Right_Channel if Left had Gain added
    btfsc    status,Z        
    incf     Right_Channel        ; Increment Right_Channel if no gain was on Left_Channel
    bcf      status,Z
    movf     Left_Channel,W       ; Test if Left Channel has Gain
    btfss    status,Z        
    bsf      Gain_on_Left         ; Set bit if Gain was added to Left_Channel
    call     Gain_NoGain_Right
    bsf      CW_Rotate
    return


Left_CCW
    movf    Right_Channel        ; Move Right_Channel so no increment occur on Left_Channel if Right had Gain added
    btfsc   status,Z
    incf    Left_Channel         ; Increment Left_Channel if no gain was on Right_Channel
    bcf     status,Z
    movf    Right_Channel,W      ; Test if Right Channel has Gain
    btfss   status,Z        
    bsf     Gain_on_Right        ; Set bit if Gain was added to Right_Channel
    call    Gain_NoGain_Left
    return



Gain_NoGain_Right
    movf    volume_data,W        ; Move volume_data into working for transmit if no gain is on the Left
    btfss   Gain_on_Left    
    goto    CW_Left
    movlw   2                    ; If gain is on the Left substract 1db as the rotate was CW
    subwf   volume_Left
    movf    volume_Left,W
CW_Left
    bcf     portd,2               ; Transmits
    movwf   sspbuf
Wait_Right
    btfss   pir1,SSPIF            ; Wait for transmit complete
    goto    Wait_Right
CW_Right
    movf    volume_data,W         ; Move volume_data into working for transmit if no Gain was on Left
    btfsc   Gain_on_Left
    goto    CW
    movlw   2                     ; If no gain was substracted from Left_Channel add 1db to Right_Channel
    addwf   volume_Right
    movf    volume_Right,W
CW
    bcf      pir1,SSPIF             ; Wait for transmit complete
    movwf    sspbuf
Wait2_Right
    btfss    pir1,SSPIF
    goto     Wait2_Right
    bsf      portd,2                ; Disable CS PGA2310
    bcf      intcon,RBIF            ; Clear interrupts
    bcf      pir1,SSPIF
    btfsc    Gain_on_Left           ; Test if gain was on Left to decrement count because 1db was substracted
    decfsz   Left_Channel
    return
    bcf      Gain_on_Left          ; If the Left_Channel is zero then no gain is on Left clear the Gain bit
    return

Gain_NoGain_Left
    movf     volume_data,W         ; Move volume_data into working for transmit if gain is on the Right
    btfsc    Gain_on_Right
    goto     CCW_Left
    movlw    2                     ; If no gain on Right_Channel then add 1db as rotate was CCW
    addwf    volume_Left
CCW_Left
    movf     volume_Left,W         ; Transmit
    bcf      portd,2
    movwf    sspbuf
Wait3_Left
    btfss    pir1,SSPIF            ; Wait for transmit complete
    goto     Wait3_Left
    movf     volume_data,W         ; Move volume_data into working for transmit if gain is on the Right
    btfss    Gain_on_Right    
    goto     CCW_Right
    movlw    2                     ; If gain is on the Right substract 1db as the rotate was CCW
    subwf    volume_Right
    movf     volume_Right,W
CCW_Right
    bcf      pir1,SSPIF             ; Transmit
    movwf    sspbuf
Wait4_Left
    btfss    pir1,SSPIF             ; Wait for transmit complete
    goto     Wait4_Left
    bsf      portd,2                ; Disable PGA2310
    bcf      intcon,RBIF            ; Clear inerrupts
    bcf      pir1,SSPIF
    btfsc    Gain_on_Right    
    decfsz   Right_Channel         ; Test if gain was on Right to decrement count because 1db was substracted
    return
    bcf      Gain_on_Right         ; If the Left_Channel is zero then no gain is on Left clear the Gain bit
    return

Transmit
    bcf      portd,2               ; enable PGA2310
    movwf    SSPBUF                ; Transmit Volume data
Spi_wait
    btfss   pir1,SSPIF             ; wait until data is sent
    goto    Spi_wait
    bcf     pir1,SSPIF             ; clear interrupt flag
    movwf   SSPBUF
Spi_wait2
    btfss   pir1,SSPIF             ; wait until data is sent
    goto    Spi_wait2
    bsf     portd,2                ; disable PGA2310
    bcf    intcon,RBIF             ; clear interrupts
    bcf    pir1,SSPIF
    return
    end
 
Last edited:
Top