-- ********************************* -- *** Robosapien IR-OUT control *** -- ********************************* -- *** Created by Mark Craig *** -- ********************************* -- Filename: saplib2.jal -- Date: 09/04/2005 -- File Version: v1.0 -- Written by: Mark Craig (*) -- Homepage: http://homepages.strath.ac.uk/~lau01246 -- Project : Robosapien -- Function: take control of robosapien through original PCB -- by sending IR commands directly to the PCB (as -- opposed to the IR-receiver). -- also receives IR from remote. -- (*): The delays are created using the following address: -- Generated by http://www.golovchenko.org/cgi-bin/delay (January 1, 2002 version) -- See also various delay routines at http://www.piclist.com/techref/microchip/delays.htm -- (C): You are free to copy, use, distribute etc. but give credit where due. -- var volatile bit ir_in_pin is pin_a0 -- var volatile bit ir_out_pin is pin_a3 -- Modified for use with JAL compiler -- the send_sap is just the assembler whereas the read_sap is mostly JAL. -- send_sap is pseudo but read_sap isn't, eg: -- send_sap = 0h81 will send h'81' to robosapien's IR-OUT pin -- read_sap( XYZ ) will return the IR code from the remote to var XYZ -- *** Send routine, sends command through ir_out_pin to robosapien's PCB *** procedure send_sap'put( byte in txreg ) is var byte bitcount, d1, d2 assembler local send_loop, DelayX, DelayX_0, DelayX_1, done movlw 0h_08 ; 8 bits of data movwf bitcount ; a counter for bits bcf ir_out_pin ; Low (start bit) PORTA,3 ; for 8/1200s movlw 0d_16 call Delayx send_loop: rlf txreg, f ; roll leftmost bit into carry bsf ir_out_pin ; high PORTA,3 movlw 0d_2 ; 1/1200 btfsc 0h0003,0d00 ; if carry = 0 skip, STATUS,C movlw 0d_8 ; 4/1200 call Delayx bcf ir_out_pin ; low PORTA,3 movlw 0d_2 call Delayx decfsz bitcount, f ; one less data bit, skip when 0 goto send_loop ; more bits left, delay this one bsf ir_out_pin ; Stop high. PORTA,3 goto done DelayX: movwf d2 DelayX_0: ;409 cycles movlw 0x_88 movwf d1 DelayX_1: decfsz d1, f goto DelayX_1 ;2 cycles nop nop ;4 cycles (including call) decfsz d2, f goto DelayX_0 return done: end assembler end procedure --; *** Read IR *** procedure alarm_triggered( byte in command_rec ) is -- if command_rec != 0 then -- this is already checked before alarm_triggered is called -- send_sap = command_rec send_sap = master_command_program_ex -- end if end procedure procedure find_start is while( ir_in_pin == on ) loop read_from_pic( pic_clock_command ) if ( pic_clock_command != 0 ) then alarm_triggered( pic_clock_command ) end if delay_10us( 1 ) -- 10us delay end loop end procedure procedure find_fall( byte out timetaken ) is -- find falling edge and return time taken in 100's of uS timetaken = 0 while( ir_in_pin == on ) loop timetaken = timetaken + 1 delay_10us( 5 ) -- 50us delay end loop end procedure procedure find_rise( byte out timetaken ) is -- find rising edge and return time taken in 100's of uS timetaken = 0 while( ir_in_pin == off ) loop timetaken = timetaken + 1 delay_10us( 5 ) -- 50us delay end loop end procedure procedure read_sap( byte out command ) is -- read command from IR var byte time_fall, time_rise find_start -- wait for start of transmission ( and check for commands from pic clock ) delay_10us( 1 ) -- give it a little time to settle find_rise( time_rise ) -- start bit is low for 8/1200s delay_10us( 1 ) -- give it a little time to settle if ( time_rise > 55 & time_rise < 65 ) then -- we have the start of a command on IR for 8 loop -- 8 bits in a byte find_fall( time_fall ) -- look at length of on pulse. denotes bit: 1/1200s for 0, 4/1200s for 1 if ( time_fall < 16 ) then -- which side of 2/1200 is it? -- we have a 0 bit assembler bcf 0h0003,0d00 ; carry = 0 STATUS,C rlf command, f ; rotate carry into command end assembler else -- we have a 1 bit assembler bsf 0h0003,0d00 ; carry = 1 STATUS,C rlf command, f ; rotate carry into command end assembler end if find_rise( time_rise ) -- this should be 1/1200s but for simplicity is ignored end loop else command = 0h55 -- error value -- as only values from 0x80 to 0xFF are valid. end if end procedure -- 1/1200s is 0.000833333s or 833us or 8 x 100us -- 4/1200s is 0.003333333s or 3333us or 33 x 100us -- 8/1200s is 0.006666666s or 6666us or 66 x 100us -- Timing based on 1/1200 second clock (~.833ms) -- Signal is normally high (idle, no IR). -- Start: signal goes low for 8/1200 sec. -- Data bits: for each of 8 data bits, space encoded signal depending on bit value -- Sends the most significant data bit first -- If the data bit is 0: signal goes high for 1/1200 sec, and low for 1/1200 sec. -- If the data bit is 1: signal goes high for 4/1200 sec, and low for 1/1200 sec. -- BTW: The first bit (msb) is always 1 (valid codes are from $80 to $FF) -- When completed, signal goes high again. -- No explicit stop bit. Minimal between signals is not known.