To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.handyboardOpen lugnet.robotics.handyboard in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / Handy Board / 80
79  |  81
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
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR