Subject:
|
Sony IR Transmission Routine
|
Newsgroups:
|
lugnet.robotics.handyboard
|
Date:
|
Tue, 20 Feb 1996 05:23:53 GMT
|
Original-From:
|
Pete McCann <MCCAP@antispamCS.WUSTL.EDU>
|
Viewed:
|
2124 times
|
| |
| |
Here's an interrupt routine I wrote to emulate Sony remote controls
using the IR driver circuitry on the handyboard. The usage instructions
are in the file. Note that you will need some IR LEDs and a little bit
of circuitry like the one advertised recently by raest@vnet.net on this
list (this is not an endorsement: I have not used his product). Hope
you find this useful. Detailed documentation is provided below. Enjoy!
--
Pete McCann mccap@cs.wustl.edu
Department of Computer Science http://swarm.wustl.edu/~mccap/
Washington University in St. Louis
*
* sony-transmit.asm
*
* An assembly language interrupt routine to transmit sony codes over
* an infrared LED. To use this code with the handyboard, you will need
* to first properly attach an infrared emitter to J7 on the handyboard.
* Dont ask me where to get one.
*
* For use with sony-ir.asm which was written
* by Brian Silverman (bss@media.mit.edu)
* ported to IC and Handy Board by Fred Martin (fredm@media.mit.edu)
* January 27, 1996
*
* This code was written by Pete McCann (mccap@cs.wustl.edu)
* February 14, 1996
*
* Copyright 1996 Pete McCann
* You may freely modify and distribute this code for non-commercial use,
* so long as this copyright notice remains intact.
*
*
* Usage: compile this file using a command like
* as11_ic sony-transmit.asm
* you should get a file called sony-transmit.icb. Then,
* at the ic prompt with your handyboard connected, type
* load sony-transmit.icb
* (this command can be put into a .lis file, if you wish.)
* Once the file is loaded, you should have the following
* functions defined:
* sony_data(int)
* sony_press(int)
* Call the function sony_data with the 8-bit value you wish to
* send. Then call the function sony_press(1) to start sending.
* call the function sony_press(0) to stop sending. Note that
* if you are using the sony-ir.asm to receive this data, you
* need a substantial delay (at least 40ms) between sends in
* order to reset the repeat-blocking feature of that routine.
* This has not yet been tested on actual Sony equipment, only
* the sony-ir.asm routine, but it emulates the waveform of
* an actual Sony remote quite well.
*
#include <6811regs.asm>
org MAIN_START
old_routine_address fdb 0 ; Store a ptr to old interrupt.
ir_data_out fdb 0 ; Data being transmitted.
ir_data_shift fdb 0 ; Bit being transmitted.
op_state fcb 0 /* What we should be doing next:
0 = Start sequence
-1 = Send data (use data_shift as mask)
1 = Sleeping */
op_phase fcb 0 /*; What phase of the current operation
; 1 = transmit on
; 0 = transmit off */
repeat_count fcb 0 /*; Number of times to repeat before
; sleeping. */
ir_timer_out fcb 0
ir_timer_last fcb 0
subroutine_initialize_module:
#include <ldxibase.asm>
* install millisec routine
ldd TOC4INT,X ; SystemInt on TOC4
std millisec_exit+1
* install ourself as new vector
ldd #millisec_routine
std TOC4INT,X
rts
* the millisec routine is installed into the pcodes "SystemInt" routine,
* which is called every millisecond
millisec_routine
inc ir_timer_out
millisec_exit
JMP $0000 ; this value poked in by init routine
* This routine gets called whenever the OC2 timer expires. The state of
* the IR output is set to toggle upon each call. This routine decides
* how much time to wait until the next toggle.
transmit_ir
ldx #BASE
bset TFLG1,X $40 ; Acknowledge the interrupt.
ldaa op_state
bmi compute_bit
bgt do_sleep
setup_start:
ldaa repeat_count
bne go_start
ldaa #2
staa repeat_count
go_start:
ldaa op_phase
beq start_time_off
start_time_on:
clr op_phase
ldd #4800 ; Delay for 2.4ms
jmp store_interval
start_time_off:
ldaa #1
staa op_phase
start_off_normal:
ldaa #-1 ; Go to transmit data state.
staa op_state
ldd #1200 ; Delay for 0.6ms
jmp store_interval
do_sleep:
ldaa ir_timer_out
blt snooze_button
bset TCTL1,X $40 ; Set the OC control to toggle the bit.
ldaa #0
staa op_state
ldaa #1
staa op_phase
ldd #1200 ; Delay for another 0.6 ms
bra store_interval
snooze_button:
ldd #20000 ; Delay another 10ms
bra store_interval
compute_bit:
ldaa op_phase
beq transmit_bit_off
transmit_bit_on:
ldaa #0
staa op_phase ; Toggle the phase.
* Compute how long to delay.
clc ; Clear carry bit so it wont be rotated in.
ldd ir_data_shift
bne transmit_bit
sec ; Set the carry bit so it gets rotated in.
transmit_bit
rolb
rola
std ir_data_shift
andb ir_data_out+1 ; Test this bit of ir_data.
bne transmit_one
anda ir_data_out
bne transmit_one
bra transmit_zero
transmit_one
ldd #2400 ; Delay 1.2 ms
bra store_interval
transmit_zero
ldd #1200 ; Delay 0.6 ms
bra store_interval
transmit_bit_off:
ldaa #1
staa op_phase ; Toggle the phase.
ldd ir_data_shift
anda #$08 ; Check to see if bit 12 is set.
bne finish_data
ldd #1100 ; Delay 0.6 ms
bra store_interval
* if this is the last bit, wait 25 or 60ms, depending on repeat_count.
finish_data:
ldx #BASE
bclr TCTL1,X $C0 ; Clear the OC control bits.
bclr PORTA,X $40 ; Clear the OC2 pin.
bset TCTL1,X $40 ; Set the OC control to toggle the bit.
clr op_state ; Setup start sequence.
ldaa #1
staa op_phase ; Be sure to have the proper phase.
clr ir_data_shift
clr ir_data_shift+1 ; Clear the shift mask.
dec repeat_count ; Check the repeat count.
bne go_next_repeat
bra go_next_repeat
* If repeat count got to zero, start sleeping.
ldaa #1
staa op_state ; Go into sleep state.
ldaa #0
suba #60
staa ir_timer_out ; Set the millisecond timer for 60ms.
bclr TCTL1,X $C0 ; Clear the OC control bits.
ldd #20000 ; Delay 10ms
bra store_interval
go_next_repeat
ldd #51200 ; Delay 25ms + 0.6 for last bit.
bra store_interval
store_interval
ldx #BASE
addd TOC2,X ; Add it to TOC2.
std TOC2,X ; Store it in TOC2.
bra transmit_ir_exit
transmit_ir_exit
rti
* call this routine with register B set to desired transmission value.
subroutine_sony_data:
ldaa #$08 ; The Sony code suffix.
std ir_data_out ; The actual 8-bits of code.
clr ir_data_shift
clr ir_data_shift+1
clr repeat_count
clr op_state
ldaa #1
staa op_phase
clra
rts
* call with 1 to turn on; 0 to turn off
subroutine_sony_press:
pshx
tstb
beq sony_transmit_off
* retain the old interrupt vector.
#include <ldxibase.asm>
ldd TOC2INT,X
std old_routine_address
* install ourself as new vector
ldd #transmit_ir
std TOC2INT,X
ldx #BASE
bclr TCTL1,X $C0 ; Clear the OC control bits.
bclr PORTA,X $40 ; Clear the OC2 pin.
ldaa #$08
staa ir_data_out
clr ir_data_shift
clr ir_data_shift+1
clr repeat_count
clr op_state
ldaa #1
staa op_phase
ldx #BASE
bset TCTL1,X $40 ; Set the OC control to toggle the bit.
ldx #BASE
ldd #1200 ; Delay 0.6ms before beginning.
addd TCNT,X
std TOC2,X ; Store it in TOC2.
bset TFLG1,X $40 ; Acknowledge the interrupt.
bset TMSK1,X $40 ; enable toc2 interrupt
clra ; Return 1.
ldab #1
pulx
rts
sony_transmit_off:
ldx #BASE
bclr TMSK1,X $40 ; disable toc2 interrupt.
* return control to the old vector.
#include <ldxibase.asm>
ldd old_routine_address
std TOC2INT,X
* turn off the transmitter.
ldx #BASE
bclr TCTL1,X $C0 ; Disconnect OC2 from output pin.
bclr PORTA,X $40 ; Clear the OC2 pin.
ldd #0
pulx
rts
|
|
1 Message in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|