;*************************************************************************** ;* ;* G3 iPod test application ;* ;* Copyright 2004, 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 TXipod1 =R19 ;first variable byte of message .def TXipod2 =R20 ;checksum ;***** 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 ;* ;*************************************************************************** ;*************************************************************************** ;* ;* G3 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 TXipod1, 0x10 ldi TXipod2, 0xeb rcall ipod_packet sbis PINB,btnFwd ;if button not pressed, skip out of loop rjmp ipod_fwd rjmp ipod_rel ipod_rev: ldi TXipod1, 0x08 ldi TXipod2, 0xf3 rcall ipod_packet sbis PINB,btnRev ;if button not pressed, skip out of loop rjmp ipod_rev2 rjmp ipod_rel ipod_rel: ldi TXipod1, 0x00 ;button release code ldi TXipod2, 0xfb 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 ;*xxxx Rate is 9600 baud (=125 cycles/bit @ 1.2MHz) !!! from g2 spec!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;* Rate is 19047 baud (=63 cycles/bit @ 1.2MHz) ;* (19200 is hard to do exactly because it is 62.5 cycles/bit) ;* ;* input: TXbyte ;* registers: bitcnt, TXbyte, temp ;* stack: one level (UART_delay) ;* ;*************************************************************************** iputchar: ldi bitcnt,10 ;1+8+1 stopbit 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: ldi temp,15 ; 1 1 rcall UART_delay ; 52 52 nop ; 1 1 nop ; 1 1 lsr TXbyte ;Get next bit 1 1 dec bitcnt ;If not all bit sent 1 1 brne iputchar1 ; send next 2 2 ret ;*************************************************************************** ;* ;* G3 iPod output routine - ipod_packet ;* ;* Format: output normally low ;* | output high, 500 uSec ;* | output message @ 8N1, 9600 baud, lsb first ;* | output high 4 extra bits ;* loop| low for ~11.16 mSec ;* ;* VOL+ 0x55 0x03 0x02 0x00 0x02 0xE9 ;* VOL- 0x55 0x03 0x02 0x00 0x04 0xF7 ;* SKIP>> 0x55 0x03 0x02 0x00 0x10 0xEB ;* < UARTdelay) ;* ;*************************************************************************** ipod_packet: ldi TXbyte, 0x00 ; stop bits (inverted) ldi bitcnt,10 ; send 10 stop bits (500uS) rcall iputchar2 ; alternate entry doesn't have start bit ldi TXbyte, 0x55 rcall iputchar ldi TXbyte, 0x03 rcall iputchar ldi TXbyte, 0x02 rcall iputchar ldi TXbyte, 0x00 rcall iputchar mov TXbyte, TXipod1 rcall iputchar mov TXbyte, TXipod2 ldi bitcnt,14 ; 1+8+1 stopbit + 4 extra stop bits rcall iputchar0 cbi PORTB,ipodTx ; bring back down to 0 ldi temp2,17 ; (774 + 3) * 17 = 13209 ~= 11 msec ldi temp, 0 ipod_packet2: rcall UART_delay ; 256 * 3 + 6 = 774 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·b + 6 cycles (including rcall and ret) ;* ;* High registers used: temp ;* ;*************************************************************************** ;3 cycles (rcall) UART_delay: dec temp ;1 cycle brne UART_delay1 ;2/1 cycles ret ;4 cycles