Код: Выделить всё
;----------------------------------------------------------------------------
;Title : RC-5 IR transmitter
;Version: 1.00
;Target : ATmega48
;Author : wubblick@yahoo.com
;AVR Assembler 2.0 Beta
;----------------------------------------------------------------------------
;Fuse bits:
;SELFPRGEN = 1 (default)
;BOOTSZ1 = 0 (default)
;BOOTSZ0 = 0 (default)
;BOOTRST = 1 (default)
;RSTDISBL = 1 (default)
;DWEN = 1 (default)
;SPIEN = 0 (default)
;WDTON = 1 (default) WDT disabled
;EESAVE = 1 (default)
;BODLEVEL2 = 1 (default) BOD disabled
;BODLEVEL1 = 1 (default)
;BODLEVEL0 = 1 (default)
;CKDIV8 = 1 CK/1
;CKOUT = 1 (default)
;SUT1 = 1 (default) 14CK + 65 ms
;SUT0 = 0 (default)
;CKSEL3 = 0 (default) RC Oscillator 8 MHz
;CKSEL2 = 0 (default)
;CKSEL1 = 1 (default)
;CKSEL0 = 0 (default)
;----------------------------------------------------------------------------
;Ports usage:
;Port PD2 (INT0) used for push button 1 (pre-focusing), active LOW.
;Port PD3 (INT1) used for push button 2 (shutter release), active LOW.
;Ports PC0, PC1, PC2, PC3 used to drive IR LED in parallel (via current
;limitting resistors), active LOW.
;Ports PB3, PB4, PB5 used for jumpers JP1, JP2, JP3 correspondingly,
;LOW - closed, HIGH - open.
;Jumpers table:
;JP1 JP2 JP3
; 1 1 1 - test mode (pulses generation with 1 ms period)
; 0 1 1 - RC-5 mode
; X 0 X - Reserved
; X X 0 - Reserved
;----------------------------------------------------------------------------
;DEBUG .include "m48def.inc"
.include "m8def.inc"
;----------------------------------------------------------------------------
;Constantes:
;DEBUG .equ FCLK = 8000000 ;clock frequency (internal RC) [Hz]
.equ FCLK = 10000000 ;clock frequency (internal RC) [Hz]
.equ SYS = 0 ;RC-5 system number - DEBUG
.equ COM1 = 1 ;RC-5 command code for button 1
.equ COM2 = 2 ;RC-5 command code for button 2
.equ CB = 0x20 ;RC-5 control bit position
;----------------------------------------------------------------------------
;Ports definition:
;Port B:
.equ JP1 = exp2(PB3) ;jumper 1 port
.equ JP2 = exp2(PB4) ;jumper 2 port
.equ JP3 = exp2(PB5) ;jumper 3 port
.equ DIRB = 0x00 ;port B direction
.equ PUPB = 0xFF ;port B pull-ups/initial values
;Port C:
.equ LED1 = exp2(PC0) ;IR LED port 1
.equ LED2 = exp2(PC1) ;IR LED port 2
.equ LED3 = exp2(PC2) ;IR LED port 3
.equ LED4 = exp2(PC3) ;IR LED port 4
.equ LED = LED1 | LED2 | LED3 | LED4
.equ DIRC = LED ;port C direction
.equ PUPC = 0xFF ;port C pull-ups/initial values
;Port D:
.equ PBTN1 = exp2(PD2) ;push button 1 port
.equ PBTN2 = exp2(PD3) ;push button 2 port
.equ DIRD = 0x00 ;port D direction
.equ PUPD = 0xFF ;port D pull-ups/initial values
;----------------------------------------------------------------------------
;Macro: generate IR pulse @0 [uS] modulated with @1 [Hz] :
.macro Pulse
ldi HalfP,(FCLK / 2 / @1)
ldi tempL,byte1((@0 * @1 / 100000 - 5) / 10)
ldi tempH,byte2((@0 * @1 / 100000 - 5) / 10)
rcall DoPls
.endm
;----------------------------------------------------------------------------
;Macro: generate pause @0 [uS]:
.macro Pause
ldi tempL,byte1((@0 * FCLK / 100 / 100000 - 5) / 10)
ldi tempH,byte2((@0 * FCLK / 100 / 100000 - 5) / 10)
rcall DoPau
.endm
;----------------------------------------------------------------------------
;Global Register Variables:
.def temp = r16 ;temporary register temp
.def tempL = r17 ;temporary register tempL
.def tempH = r18 ;temporary register tempH
.def Cnt = r19 ;temporary register Cnt
.def System = r20 ;RC-5 system code and control bit
.def Command = r21 ;RC-5 command code
.def HalfP = r22 ;modulation half-period
.def tempC = r23 ;temporary register tempC
.def tempS = r24 ;temporary register tempS
;----------------------------------------------------------------------------
.CSEG ;Code segment
;----------------------------------------------------------------------------
;Interrupt vectors:
.org 0
rjmp Init ;reset vector
.org INT0addr
rjmp Btn1 ;push button 1 interrupt service
.org INT1addr
rjmp Btn2 ;push button 2 interrupt service
;----------------------------------------------------------------------------
;Push button 1 interrupt:
Btn1: ldi Command,COM1
reti
;----------------------------------------------------------------------------
;Push button 2 interrupt:
Btn2: ldi Command,COM2
reti
;----------------------------------------------------------------------------
;Initialization:
Init: ldi tempL,Byte1(RAMEND) ;locate stack
ldi tempH,Byte2(RAMEND)
out SPH,tempH
out SPL,tempL
ldi temp,(1<<ACD) ;analog comparator disable
out ACSR,temp
ldi temp,PUPB
out PORTB,temp ;init PORTB and on/off pullup
ldi temp,DIRB
out DDRB,temp ;set PORTB direction
ldi temp,PUPC
out PORTC,temp ;init PORTC and on/off pullup
ldi temp,DIRC
out DDRC,temp ;set PORTC direction
ldi temp,PUPD
out PORTD,temp ;init PORTD and on/off pullup
ldi temp,DIRD
out DDRD,temp ;set PORTD direction
ldi temp,(1<<SM1) | (1<<SE) ;sleep enable, power down
;DEBUG out SMCR,temp
out MCUCR,temp
ldi temp,(1<<INT0) | (1<<INT1) ;INT0 and INT1 enable
;DEBUG out EIMSK,temp
out GICR,temp
ldi System,SYS ;load RC-5 system number
rjmp Main
;----------------------------------------------------------------------------
;Get system from jumpers:
;temp - system code
GetSys: clr temp
sbis PINB,log2(JP1)
sbr temp,exp2(0)
sbis PINB,log2(JP2)
sbr temp,exp2(1)
sbis PINB,log2(JP3)
sbr temp,exp2(2)
ret
;----------------------------------------------------------------------------
;Delay:
;Cnt - cycles number (17 minimum)
; ldi Cnt,Cycles ;1
; rcall Delay ;3
Delay: subi Cnt,13 ;1
lsr Cnt ;1 Cnt / 2
brcs de1 ;2(1)
de1: lsr Cnt ;1 Cnt / 2
brcs de2 ;2(1)
de2: brcs de3 ;2(1)
de3: dec Cnt ;1
nop ;1
brne de3 ;2(1)
ret ;4
;----------------------------------------------------------------------------
;Generate IR modulated pulse:
;tempH:tempL - pulse duration in loop cycles
;Pulse - modulation half-period
DoPls: ldi temp,~LED ;1
out PORTC,temp ;1
ldi Cnt,-3 ;1
add Cnt,HalfP
rcall Delay ;Pulse - 3
ldi temp,LED ;1
out PORTC,temp ;1
ldi Cnt,-7 ;1
add Cnt,HalfP
rcall Delay ;Pulse - 7
subi tempL,1 ;1
sbci tempH,0 ;1
brcc DoPls ;2(1)
ret
;----------------------------------------------------------------------------
;Generate pause:
;tempH:tempL - pause duration in loop cycles
DoPau: ldi Cnt,96
rcall Delay ;96
subi tempL,1 ;1
sbci tempH,0 ;1
brcc DoPau ;2(1)
ret
;----------------------------------------------------------------------------
;Transmit bit in manchester code:
Manch: brcs bit1
nop
bit0: Pulse 889, 36000
Pause 889
ret
bit1: Pause 889
Pulse 889, 36000
ret
;----------------------------------------------------------------------------
;Transmit RC-5:
;System - RC-5 system number and control bit (X,X,CB,S4,S3,S2,S1,S0)
;Command - RC-5 command (X,X,C5,C4,C3,C2,C1,C0)
Tx_Rc5: mov tempS,System
ori tempS,0xC0 ;add start bits
mov tempC,Command
lsl tempC ;shift command code
lsl tempC
lsl tempS
rcall Manch ;bit 01: Start bit 1
lsl tempS
rcall Manch ;bit 02: Start bit 2
lsl tempS
rcall Manch ;bit 03: Control bit
lsl tempS
rcall Manch ;bit 04: System bit 4
lsl tempS
rcall Manch ;bit 05: System bit 3
lsl tempS
rcall Manch ;bit 06: System bit 2
lsl tempS
rcall Manch ;bit 07: System bit 1
lsl tempS
rcall Manch ;bit 08: System bit 0
lsl tempC
rcall Manch ;bit 09: Command bit 5
lsl tempC
rcall Manch ;bit 10: Command bit 4
lsl tempC
rcall Manch ;bit 11: Command bit 3
lsl tempC
rcall Manch ;bit 12: Command bit 2
lsl tempC
rcall Manch ;bit 13: Command bit 1
lsl tempC
rcall Manch ;bit 14: Command bit 0
ret
;----------------------------------------------------------------------------
;Main program:
Main: sei ;global interupt enable
;TODO pull-up off!
sleep ;go to power down
cli ;global interupt disable
;TODO pull-up on!
rcall GetSys ;read system from jumpers
tst temp
brne m1
;generate test pattern:
test: ldi temp,LED
out PORTC,temp
Pause 1000
ldi temp,~LED
out PORTC,temp
rjmp test
;generate RC-5 pattern:
m1: mov temp,Command
com Command
next: cp temp,Command
breq same
ldi tempL,CB
eor System,tempL ;invert control bit
same: mov Command,temp
rcall Tx_Rc5 ;transmit RC-5 pattern
Pause 88900 ;wait 88.9 mS
;debounce buttons:
sbic PIND,log2(PBTN2) ;check push button state
rjmp dbnc2
ldi temp,COM2
rjmp next
dbnc2: sbic PIND,log2(PBTN1) ;wait push button 2 release
rjmp Main
ldi temp,COM1
rjmp next
;----------------------------------------------------------------------------