. Den använder den CLC, Configurable Logic Cell som finns i denna serie PICs. Jag har skrivit om litet för assemblern i MPLABX, lagt till knappar och svängt ledden eftersom en utgång kan sänka mera än den sourcar.
Kod: Markera allt
; irremote.asm - Implement an IR-Remote for Denon receivers
;
; Based on Microchip sample TB3096
;
; By: Anders Gustafsson, http://www.dalton.ax/irremote
;
; http://ww1.microchip.com/downloads/en/DeviceDoc/40001715D.pdf
;
; http://ww1.microchip.com/downloads/en/AppNotes/90003096A.pdf
;
; Summary:
; Init everything, then go to sleep. Interrupt on change wakes up on keypress
; transmit bytes, then go back to sleep.
;
; History
; 2017-01-07 0.1 Working sample
;
errorlevel -302 ; Mute that annoying "Register in operand not in bank 0. Ensure that bank bits are correct"
;
#include "p16f1708.inc"
;#define TX_DATA1 0x33 ; this is the date that will be transmitted - example.
;#define TX_DATA2 0xd1 ; Tape 2 first
;#define TX_DATA3 0x34
;#define TX_DATA4 0x2f ; Tape 2 second (command bits inverted)
; CONFIG1
; __config 0xFFE7
__CONFIG _CONFIG1, _FOSC_ECH & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
; CONFIG2
; __config 0xFFFF
__CONFIG _CONFIG2, _WRT_OFF & _PPS1WAY_ON & _ZCDDIS_ON & _PLLEN_ON & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_ON
bank0 udata_shr
tx_register res 1 ; RAM location for transmit data (Common RAM)
tx_counter res 1 ; counts bits in the transmission
baud_counta res 1 ; 0x72 ; counter for baud rate delay
baud_countb res 1 ; 0x73
deb_count res 1 ; counter for debounce
d1 res 1 ; Delay variables
d2 res 1
key res 1 ; Key pressed
RES_VECT CODE 0x0000 ; processor reset vector
GOTO START ; go to beginning of program
; TODO ADD INTERRUPTS HERE IF USED
MAIN_PROG CODE ; let linker place main program
START
nop
banksel ANSELB
clrf ANSELB ; make port B digital
clrf ANSELA ; make port B digital
clrf ANSELC ; make port C digital
banksel TRISC
clrf TRISC ; port C all outputs
movlw 0xE0
movwf TRISB ; port B all outputs, except RB7, RB6, RB5
clrf TRISA ; port A all outputs
#include "pwm3and.inc" ; load Configurable Logic Cell settings.
; these settings allow PWM3 OUT to pass through,
; or pin outputs ?0?.
banksel RC2PPS
movlw 0x04 ; 0x04 - 00100 = Rxy source is LC1OUT
movwf RC2PPS ; selects CLC1 output for RC2 pin.
banksel VREGCON
movlw 0x03
movwf VREGCON ; low power mode for Sleep
banksel WPUB
movlw 0xE0
movwf WPUB ; turn on weak pull-up on RB7,6,5
banksel OPTION_REG
bcf OPTION_REG, 7 ; enable weak pull-ups
banksel IOCBN
bsf IOCBN, 7 ; enable interrupt-on-change (falling edge) on RB7
bsf IOCBN, 6 ; enable interrupt-on-change (falling edge) on RB6
bsf IOCBN, 5 ; enable interrupt-on-change (falling edge) on RB5
; bcf IOCBF, 7 ; clear interrupt-on-change flag.
; bcf IOCBF, 6 ; clear interrupt-on-change flag.
; bcf IOCBF, 5 ; clear interrupt-on-change flag.
clrf IOCBF
banksel OSCCON
movlw 0x78
movwf OSCCON ; 16 MHz oscillator
banksel PR2
movlw .125 ; set up period of 32 kHz
movwf PR2 ; for Timer2.
banksel PWM3DCH
movlw .66 ; 50% duty cycle
movwf PWM3DCH ; for PWM3.
clrf PWM3DCL
banksel T2CON
clrf T2CON ; 1:1 prescaler for Timer2.
bsf T2CON, TMR2ON ; turn on Timer2.
banksel PWM3CON
bsf PWM3CON, 7 ; turn on PWM3
banksel INTCON
bcf INTCON, IOCIF ; make sure interrupt flag is clear
bsf INTCON, IOCIE ; and then enable the interrupt
; Testing
; movlw 0x80 ; transmit data byte 2
; goto test
; movlw 7
; movwf key
; movlw 8
; movwf d1
; clrf d2
;loop
; movf d1,w
; btfsc key,7
; addwf d2,f
; rlf key,f
; decfsz d1,f
; goto loop
main_loop
sleep ; go to sleep - low current mode.
nop
nop ; wake-up occurs here.
nop ; does not go to interrupt vector because
; GIE is not enabled
debounce
movlw 0xff
movwf deb_count ; initialize debounce counter.
deb_a
call Delay_275us ; Just a delay we happened to have...
; Has button been released?
; If button has been released, then the upper nibble is F
banksel PORTB
movf PORTB,w
iorlw b'00011111'
xorlw 0xff
btfss STATUS,Z
goto debounce ; No.
decfsz deb_count ; Yes. Has it been released for a while?
goto deb_a ; No.
nop ; interrupt will cause wake-up.
nop
; Should be able to read what key was pressed from
test ; IOCBF
banksel IOCBF ; Grab what caused the interrupt
movf IOCBF,w
andlw 0xe0 ; Mask out uninteresting bits
movwf key ; Save key bitmap. Bit position corresponds to key
call get_bit ; Decode
; KEY now holds key number 1..8
decf key,f ; decrement (0..7)
BCF STATUS,C ; Clear carry, so that the rotate shifts in zeroes
rlf key,f
rlf key,f ; Multiply by 4 as there is 4 bytes per key
movfw key
; transmit data byte 1
call get_data
movwf tx_register ; moved to transmit register.
call transmit
incf key,f ; increment to point to second byte
movfw key
call get_data
movwf tx_register ; moved to transmit register.
call transmit
call Delay_65ms ; 65ms delay between
incf key,f ; increment to point to third byte
movfw key
call get_data
movwf tx_register ; moved to transmit register.
call transmit
incf key,f ; increment to point to third byte
movfw key
call get_data
movwf tx_register ; moved to transmit register.
call transmit
banksel IOCBF
; bcf IOCBF, 7 ; clear interrupt-on-change flag.
; bcf IOCBF, 6
; bcf IOCBF, 5
clrf IOCBF ; clear interrupt-on-change flags.
banksel INTCON
bcf INTCON, IOCIF ; clear interrupt flag.
goto main_loop
;
; Transmit the byte in tx_register
transmit
banksel LATC
bsf LATC, 6
bcf LATC, 6 ; scope trigger
movlw 0x08 ; Number of bits to transmit
movwf tx_counter
tx_a
banksel CLC1POL
btfss tx_register, 7 ; Is bit one or zero
goto transmit_zero
goto transmit_one
next_bit
rlf tx_register, F ; rotate left to get next bit.
decfsz tx_counter, F ; decrement bit counter. Am I done?
goto tx_a ; No.
bcf CLC1POL, 3 ; Yes. Drop signal low at end of transmission.
return
transmit_zero ; Mark for 275us, space 775us
bsf CLC1POL, 3 ; CLC output = 1 (PWM3 OUT)
call Delay_275us
bcf CLC1POL, 3 ; CLC output = 0
call Delay_775us
goto next_bit
transmit_one ; Mark for 275us, space 1900us
bsf CLC1POL, 3 ; CLC outputs PWM3 OUT
call Delay_275us
bcf CLC1POL, 3 ; CLC output = 0
call Delay_1900us
goto next_bit
;bit_delay
; clrf baud_counta
; clrf baud_countb ; clear counter
;bit_delay_loop
; incf baud_counta, F
; btfss STATUS, Z ; did I roll over?
; goto bit_delay_loop ; No
; incf baud_countb, F ; Yes. Increment higher byte
; movlw 0x08
; subwf baud_countb, W
; btfss STATUS, Z ; Am I at end of bit time?
; goto bit_delay_loop ; No.
; return ; Yes.
;
; Read byte from program memory (from the manual)
; Input: Index in W
; Output: Byte in W
get_data ;Entry with desired index in W
ADDLW LOW constants
MOVWF FSR1L
MOVLW HIGH constants ;MSb sets automatically
MOVWF FSR1H
BTFSC STATUS, C ;carry from ADDLW?
INCF FSR1H, f ;yes
MOVIW 0[FSR1]
;THE PROGRAM MEMORY IS IN W
return
; Find set bit number
; Input: bitmap in key
; Output: value in key
; Thrashes: d2
get_bit
movlw 8 ; Loop counter i WREG
clrf d2 ; Clear out value in in d2
loop
btfsc key,7 ; Bit 7 set?
addwf d2,f ; Yes, add loop counter
rlf key,f ; No, rotate left and check next..
decfsz WREG,f ; decrement loop counter, is zero?
goto loop ; No, back to top
; Yes, we are done
movf d2,w ; Return with bit number in KEY
movwf key
return
;------------------------------ Delay routines ----------------------------
; Delay = 0.000275 seconds
; Clock frequency = 16 MHz
; Actual delay = 0.000275 seconds = 1100 cycles
; Error = 0 %
Delay_275us
;1098 cycles
movlw 0xDB
movwf d1
movlw 0x01
movwf d2
Delay_275us_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_275us_0
;2 cycles
goto $+1
return
; Delay = 0.000775 seconds
; Clock frequency = 16 MHz
; Actual delay = 0.000775 seconds = 3100 cycles
; Error = 0 %
Delay_775us
;3098 cycles
movlw 0x6B
movwf d1
movlw 0x03
movwf d2
Delay_775us_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_775us_0
;2 cycles
goto $+1
return
; Delay = 0.0019 seconds
; Clock frequency = 16 MHz
; Actual delay = 0.0019 seconds = 7600 cycles
; Error = 0 %
Delay_1900us
;7598 cycles
movlw 0xEF
movwf d1
movlw 0x06
movwf d2
Delay_1900us_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_1900us_0
;2 cycles
goto $+1
return
; Delay = 0.056 seconds
; Clock frequency = 16 MHz
; Actual delay = 0.056 seconds = 224000 cycles
; Error = 0 %
Delay_65ms
;223998 cycles
movlw 0xFF
movwf d1
movlw 0xAF
movwf d2
Delay_65ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_65ms_0
;2 cycles
goto $+1
return
;------------------------------ Key data ----------------------------
;
; Four bytes per key as each keycode is 16 bits, 5 address, the rest data and stopbit
; The second byte is the same, but the command bits inverted
;
constants ; Key 1
DW 0x00 ;
DW 0x00 ;
DW 0x00
DW 0x00
; Key 2
DW 0x00 ;
DW 0x00 ;
DW 0x00
DW 0x00
; Key 3
DW 0x00 ;
DW 0x00 ;
DW 0x00
DW 0x00
; Key 4
DW 0x00 ;
DW 0x00 ;
DW 0x00
DW 0x00
; Key 5
DW 0x00 ;
DW 0x00 ;
DW 0x00
DW 0x00
;Key 6
DW 0x35 ;Volume Up
DW 0x91 ;
DW 0x32
DW 0x6f
; Key 7
DW 0x31 ;Volume Down
DW 0x91 ;
DW 0x36
DW 0x6f
; Key 8
DW 0x33 ;TAPE-2
DW 0xd1 ;
DW 0x34
DW 0x2f
END