📄 ipodtest.asm
字号:
;***************************************************************************
;*
;* IPOD test application
;*
;* Copyright 2003, John Maushammer. Released under GPL license.
;* http://www.maushammer.com/systems/ipod-remote/ipod-remote.html
;*
;***************************************************************************
;*
;* Target: ATtiny12-8PI
;* +---v---+
;* pull high -> reset/PB5|1 8|vcc
;* rev button -> PB3|2 7|PB2 <-- output to ipod
;* fwd button -> PB4|3 6|PB1 not used
;* gnd|4 5|PB0 not used
;* +-------+
;*
;* Buttons are pulled high by internal pullups; connect inputs through
;* normally open switches to ground. Output goes to VCC - if using a
;* VCC=+3.3v, then protect the ipod with a 1k ohm resistor. If using a
;* VCC=+5v, then you must use a divider to bring down the voltage and
;* provide a high output impedence.
;*
;* Internal oscillator @ 1.2MHz
;*
;* Program with: stk500 -dATTINY12 -iftest.hex -O -e -pf -vf -Sf3ff
;* (stores osc cal value at last byte in memory)
;*
;***************************************************************************
.include "tn12def.inc"
;***** Pin definitions
.equ ipodTx =2 ;Transmit pin is PB2
.equ btnRev =3 ;reverse button PB3
.equ btnFwd =4 ;forward button PB4 (normally high, pulled low)
;***** Global register variables
.def temp =R16 ;temporary storage register
.def temp2 =R17
.def bitcnt =R18 ;bit counter
.def TXipod =R21
;***** OSCCAL value set by programmer
.equ osccal_value =$1ff ;last byte of memory
.cseg
.org 0 ;interrupt table:
rjmp reset
rjmp ext_int0
rjmp pin_change ;pin change
rjmp tim0_ovf ;timer
rjmp ee_rdy ;eeprom ready
rjmp ana_comp ;comparator
;***** Program Execution Starts Here
reset: ldi ZH, high((osccal_value<<1)+1) ;get value set by programmer
ldi ZL, low((osccal_value<<1)+1)
lpm ; R0<-(Z)
out OSCCAL, R0
ldi temp, 0b00000110 ; 1=out
out DDRB, temp
ldi temp, 0b00011000 ; pull up buttons (PB3 & 4)
out PORTB, temp
;***************************************************************************
;* Main loop
;*
;***************************************************************************
;***************************************************************************
;*
;* ipod remote control application
;*
;* Warning: uses all 3 stack levels: ipod_packet> putchar > delay
main_loop: sbis PINB,btnFwd ;if button not pressed, skip
rjmp ipod_fwd
sbis PINB,btnRev
rjmp ipod_rev
; other button inputs would go here...
rjmp main_loop
ipod_fwd: ldi TXipod, 0xf4
rcall ipod_wake
ipod_fwd2: rcall ipod_packet
sbis PINB,btnFwd ;if button not pressed, skip out of loop
rjmp ipod_fwd2
rjmp ipod_rel
ipod_rev: ldi TXipod, 0xf5
rcall ipod_wake
ipod_rev2: rcall ipod_packet
sbis PINB,btnRev ;if button not pressed, skip out of loop
rjmp ipod_rev2
rjmp ipod_rel
ipod_rel: ldi TXipod, 0xF0 ;button release code
rcall ipod_packet
rjmp main_loop
;***************************************************************************
;* Unused interrupts
;* shouldn't be called, but if they are, then we'll know it.
;***************************************************************************
ext_int0:
pin_change:
tim0_ovf:
ee_rdy:
ana_comp:
;***************************************************************************
;*
;* oscillator output test function. A not-quite symetrical square wave.
;*
;* For the tested chip, the correct OSCCAL value is $40
;*
;* OSCCAL=0/uncal: 149.83 --> RC osc = 1048.8 = -12.6%
;* OSCCAL=40: 172.43 1207 = + 1.0%
;* OSCCAL=80: 202.86 1420 = +18.3%
;* OSCCAL=FF: 315.80 2210.6 = +84.2%
;*
;***************************************************************************
osctest: sbi DDRB,TxD ;set direction
ot2: cbi PORTB,TxD ;send a '0' 2 cycles
; nop ; 1 cycle - this would make 50/50
nop ; 1 cycle
sbi PORTB,TxD ;send a '1' 2 cycles
rjmp ot2 ; 2 cycles
;***************************************************************************
;*
;* ipod putchar
;*
;* This subroutine transmits the byte stored in the "TXbyte" register
;* Rate is 9600 baud (=125 cycles/bit @ 1.2MHz)
;*
;* input: TXbyte
;* registers: bitcnt, TXbyte, temp
;* stack: one level (UART_delay)
;*
;***************************************************************************
iputchar: ldi bitcnt,11 ;1+8+2 stopbits
iputchar0: com TXbyte ;invert everything (so stop bits will be 1's)
sec ;start bit
; cycle count if carry set clr
; --- ---
iputchar1: brcc iputchar2 ;If carry set 1 2
cbi PORTB,ipodTx ; send a '0' 2
rjmp iputchar3 ;else 2
iputchar2: sbi PORTB,ipodTx ; send a '1' 2
nop ; 1
iputchar3: rcall UART_delay ;One bit delay total - 2*58 cycles
rcall UART_delay ; (b=17) is 9600 baud exactly.
lsr TXbyte ;Get next bit 1 1
dec bitcnt ;If not all bit sent 1 1
brne iputchar1 ; send next 2 2
ret
;***************************************************************************
;*
;* iPod output routines - ipod_wake & ipod_packet
;*
;* Format: output normally low
;* high for 45 mSec
;* | output message @ 8N2, 9600 baud, lsb first
;* loop| low for 26 mSec
;*
;* VOL+ 0xFF 0xFD 0xF2
;* VOL- 0xFF 0xFD 0xF3
;* SKIP>> 0xFF 0xFD 0xF4
;* <<SKIP 0xFF 0xFD 0xF5
;* PLAY/PAUSE 0xFF 0xFD 0xF1
;* (button release) 0xFF 0xFD 0xF0
;*
;* input: TXipod is one of these --^^
;* stack: uses 2 stack locations (iputchar > UARTdelay)
;*
;***************************************************************************
ipod_wake: sbi PORTB,ipodTx ; send a '1'
ldi temp2,69 ; (775 + ?) * 69 = 53475 ~= 44.5 msec
ldi temp, 0
ipod_wake2: rcall UART_delay1 ; 256 * 3 + 7 = 775 clocks
dec temp2
brne ipod_wake2
ret
;***************************************************************************
ipod_packet: ldi TXbyte, 0x00 ; stop bits (inverted)
ldi bitcnt,4 ; send 4 stop bits
rcall iputchar2 ; alternate entry doesn't have start bit
ldi TXbyte, 0xFF
rcall iputchar
ldi TXbyte, 0xFD
rcall iputchar
mov TXbyte, TXipod
ldi bitcnt,12 ; 1+8+2 stopbits + 1 extra stop bit
rcall iputchar0
cbi PORTB,ipodTx ; bring back down to 0
ldi temp2,40 ; (775 + ?) * 40 = 31000 ~= 25.8 msec
ldi temp, 0
ipod_packet2: rcall UART_delay1 ; 256 * 3 + 7 = 775 clocks
dec temp2
brne ipod_packet2
ret
;***************************************************************************
;*
;* UART_delay
;*
;* This delay subroutine generates the required delay between the bits when
;* transmitting and receiving bytes. The total execution time is set by the
;* constant "b":
;*
;* 3穊 + 7 cycles (including rcall and ret)
;*
;* At 1.2MHz, 17 cycles is just about right for 9600 baud.
;*
;* High registers used: temp
;*
;***************************************************************************
;3 cycles (rcall)
UART_delay: ldi temp,17 ;1 cycle
UART_delay1: dec temp ;1 cycle
brne UART_delay1 ;2/1 cycles
ret ;4 cycles
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -