; ; PIC12F675 ; Rotary Commander Controller for PAV-MP1LP Ver 0.1 ; Programmed by DD ; 2012/2/24 ; ; Data Format ; +---------------+ ; | | |I|A|X|X|O|O| GPIO I:Input O:Output A:Analog Input ; +---------------+ ; Input Data ; GP5 => Commander Shift ; AN3 => Commander Signal (Analog) ; ; Output Data ; GP1 => Piezo Speaker ; GP0 => Infrared LED ; list p=pic12F675 include "p12f675.inc" ; Defining constant ;Threshold Voltage of Rotary Commander (+10kohm, 5V) TH_POFF EQU d'23' TH_SOURCE EQU d'62' TH_MUTE EQU d'90' TH_LISTT EQU d'110' TH_SKIPF EQU d'129' TH_SKIPB EQU d'150' TH_VOLU EQU d'169' TH_VOLD EQU d'188' TH_SEL EQU d'204' TH_MODE EQU d'233' ;Rotary Commander Key Definitions OPEN EQU 0 POFF EQU 1 SOURCE EQU 2 MUTE EQU 3 LISTT EQU 4 SKIPF EQU 5 SKIPB EQU 6 VOLU EQU 7 VOLD EQU 8 SEL EQU 9 MODE EQU d'10' SHIFTF EQU d'11' SHIFTB EQU d'12' ;IR code definition CMD_ID EQU h'40' ;ID Code of PAV-MP1LP CMD_POWER EQU h'B8' CMD_ENTER EQU h'D0' CMD_MUTE EQU h'40' CMD_BACK EQU h'B0' CMD_RIGHT EQU h'10' CMD_LEFT EQU h'50' CMD_VOLU EQU h'00' CMD_VOLD EQU h'C0' CMD_HOME EQU h'8C' CMD_OPTION EQU h'CC' CMD_UP EQU h'90' CMD_DOWN EQU h'80' ; ; __FUSES _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT ; Configuration Code = 0xFFEA ; When burning PIC, the following configuration is necessary ; MCLR is OFF ; Code Protection(CP) is OFF ; Watch Dog Timer(WDT) is OFF ; Clock is Internal RC Oscillator cblock 0x20 ;Store variables above control registers ckey ;commander key (Refer constant definition) prev_ckey ;previous key to prevent from repeating (except volume) prev_ad ;previous a/d value to check voltage stability curr_ad ;current a/d value cmnd ;command to be sent which is expressed as one of CMD_XXX sndbyte ;1 byte to be sent wcnt1 ;Wait Counter1 (For Wait) wcnt2 ;Wait Counter2 (For Wait) scnt ;counter for sound endc org 0x00 ;Start of Code Space goto START ;========================================= ; Start Program ;========================================= START bcf STATUS,RP0 ;Set Bank0 clrf GPIO movlw h'7' movwf CMCON bsf STATUS,RP0 ;Set Bank1 movlw b'00111100' ;Output: GP1,GP0, Input:GP5,GP4,GP3,GP2 movwf TRISIO ;Set GPIO Input/Output movlw b'00000000' ;Interrupt OFF movwf IOC movlw b'00111100' ;GP5-GP2, pull-up movwf WPU movlw b'00000000' ;Pull-up Enable movwf OPTION_REG movlw b'01101000' ;GP5,GP3,GP2,GP1,GP0=Digital I/O AN3=Analog Input, OSC/64 movwf ANSEL bcf STATUS,RP0 ;Set Bank0 movlw b'00000000' ;A/D Converter OFF movwf ADCON0 movlw OPEN movwf prev_ckey ;prev_ckey = OPEN ;Main loop CHK_CMD call READAD ;Check rotary commander movlw OPEN ;W=OPEN (=No operation) subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If W=0 goto CHK_NXT ; goto CHK_NXT movlw VOLU ;W=VOLU ;Checking volume keys to skip repeat check subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If W=0 goto CHK_SKP ; goto CHK_SKP movlw VOLD ;W=VOLD subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If W=0 goto CHK_SKP ; goto CHK_SKP movf prev_ckey,W ;W=prev_ckey ;Prevention from key repeating subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If ckey = prev_ckey goto CHK_CMD ; goto CHK_CMD CHK_SKP call CNVCMD ;Convert ckey to cmnd (one of CMD_XXX) movwf cmnd call SENDCMD ;Send IR command movlw d'90' ;Short pause for sound movwf scnt ;This is just to extend the time of the sound. call PULSOFF decfsz scnt,F goto $-2 ;If ckey=VOLU or VOLD then wait 100ms ; to adjust key repeating interval movlw VOLU ;W=VOLU subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If W=0 call wait100ms ; call wait100ms movlw VOLD ;W=VOLD subwf ckey,W ;W=W-ckey btfsc STATUS,Z ;If W=0 call wait100ms ; call wait100ms CHK_NXT movf ckey,W movwf prev_ckey ;prev_ckey = ckey goto CHK_CMD ;================================ ; Convert Key to IRCMD ; Input: ckey ; Output: W as one of CMD_XXX ;================================ CNVCMD movf ckey,W andlw b'00001111' ;W=W and h'0F' addwf PCL,F ;The followings are conversion table. retlw d'0' ;0 retlw CMD_POWER ;1 retlw CMD_ENTER ;2 retlw CMD_MUTE ;3 retlw CMD_BACK ;4 retlw CMD_RIGHT ;5 retlw CMD_LEFT ;6 retlw CMD_VOLU ;7 retlw CMD_VOLD ;8 retlw CMD_HOME ;9 retlw CMD_OPTION ;10 retlw CMD_UP ;11 retlw CMD_DOWN ;12 return return return return ;Subroutine ;================================ ; Send IR command ; Input: cmnd ;================================ SENDCMD call PULSON ;Sending leader part 557us*16 call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSON call PULSON nop call PULSOFF ;Rest of 557us*8 call PULSOFF call PULSOFF call PULSOFF call PULSOFF call PULSOFF call PULSOFF call PULSOFF movlw CMD_ID ; Send ID code of PAV-MP1LP movwf sndbyte call SND1BYTE movlw h'FF' xorwf sndbyte,F ; Exclusive OR of CMD_ID call SND1BYTE movf cmnd,W ; Send IR command movwf sndbyte call SND1BYTE movlw h'FF' xorwf sndbyte,F ; Exclusive OR of IR command call SND1BYTE call PULSON ; Send a stop bit. call PULSOFF return ;================================ ; Send 1 Byte ;================================ SND1BYTE call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,7 ; if bit 7 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,6 ; if bit 6 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,5 ; if bit 5 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,4 ; if bit 4 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,3 ; if bit 3 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,2 ; if bit 2 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,1 ; if bit 1 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 call PULSON ; Pulse on 557.5us call PULSOFF ; Pulse off 557.5us btfsc sndbyte,0 ; if bit 0 of sndbyte = 1 call PULSOF2 ; Expand rest for 557.5us *2 return ;================================ ; 38kHz, 557uS pulse ; (27us+26us+26us+26us)*5+27uS+26us + others ; The actual measurement of the time is different from the simulation on PC. ; I don't know why...? ;================================ PULSON movlw d'5' ;*5 movwf wcnt2 PONL1 bsf GPIO,0 bsf GPIO,1 btfss wcnt2,2 bcf GPIO,1 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 bcf GPIO,0 ;14 clock movlw d'4' movwf wcnt1 decfsz wcnt1,F goto $-1 bsf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bcf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bsf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bcf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bsf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bcf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop decfsz wcnt2,F goto PONL1 bsf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bcf GPIO,0 ;14 clock movlw d'4' movwf wcnt1 decfsz wcnt1,F goto $-1 bsf GPIO,0 movlw d'3' ;13 clock movwf wcnt1 decfsz wcnt1,F goto $-1 nop nop bcf GPIO,0 ;13 clock movlw d'3' movwf wcnt1 decfsz wcnt1,F goto $-1 nop return ;================================ ; 557uS REST ;================================ PULSOFF movlw d'5' ;*5 movwf wcnt2 bsf GPIO,1 btfss wcnt2,2 bcf GPIO,1 movlw d'35' ;*35 movwf wcnt1 decfsz wcnt1,F goto $-1 decfsz wcnt2,F goto $-8 return PULSOF2 call PULSOFF call PULSOFF return ;================================ ; Read A/D ;================================ READAD clrf prev_ad ;prev_ad=0 READADLP movlw b'00001101' ;Select AN3 movwf ADCON0 bcf PIR1,ADIF bsf ADCON0,GO_DONE ;GO/DONE=1 ADWAIT btfsc ADCON0,GO_DONE ;If GO/DONE=1 goto ADWAIT ; go to ADWAIT movf ADRESH,W ;W=ADRESH subwf prev_ad,W ;W=W-prev_ad btfsc STATUS,Z ;If W=0 check stable A/D value goto $+4 ; jump movf ADRESH,W ;W=ADRESH movwf prev_ad ;prev_ad = W goto READADLP ; go to READADLP movf ADRESH,W ;W=ADRESH movwf curr_ad ;Set current A/D value movlw OPEN ;ckey=OPEN movwf ckey movf curr_ad,W ;ckeck POFF sublw TH_POFF btfss STATUS,C ;if curr_ad