(Comp.sys.hp48) Main: r 438 460 587 614 623 624 627 646 647 660 661 710 664 673 6 3 Item: 438 by stevev at greylady.uoregon.edu Author: [Steve VanDevender] Subj: IR and IR2--IR remote-control sampling programs Keyw: Date: Tue Dec 31 1991 07:44 Lines: 412 These program embody a new way of performing infrared remote control sampling on the HP-48. The previously distributed remote sampling programs sampled IR input by continually reading the IR input and immediately writing it out to memory. These programs use a different approach--they continually sample the IR input while incrementing a timing count, and only write information to memory when the IR state changes or the counter overflows. This approach increases the effective sampling rate under many circumstances and greatly reduces the amount of memory needed to store samples. I have also paid special attention to instruction timing to make sure that the timing characteristics of the sampling and playback routines are as nearly identical as possible; this has been a problem with some previous attempts at remote sampling. One of my motivations for writing these programs was that the other IR samplers I tried wouldn't work at all with my VCR. Both of these work with my VCR, although I have obtained mixed results using these programs with other kinds of remotes. I am hoping that these programs will be more effective than previous attempts, and that the techniques I have used here can be improved upon by others. There are two separate IR sampling systems included here. The first, in irsamp.star, irplay.star, ir.asc, and ir.uue, were the first programs I developed that worked. They store 3-nibble sample units--1 nibble for the current IR input state, and 2 nibbles for a repeat count. The inner loop of the sampling and playback routines runs at about 25 microseconds per loop iteration, and take about 40 microseconds to write out the sample data and re-enter the inner loop. These routines will make samples of about 90 bytes that work with my VCR. The second, in irsamp2.star, irplay2.star, ir2.asc, and ir2.uue, use 2-nibble samples containing a 1-nibble repeat count. The inner loop of these routines runs at about 23 microseconds per iteration, but sample string are a little over twice as long, at 224 bytes for samples that work with my VCR. Interestingly enough, though, Lutz Vieweg's RFP program will pack samples created by either set of routines to about the same length of 60 bytes. This posting includes STAR assembler source for all machine-language routines and ASC and uuencoded directories containing the machine- language programs and user RPL wrapping functions that perform additional type checking and provide a cleaner interface to the provided routines. The directory IR contains the 3-nibble sampling routines, and the directory IR2 contains the 2-nibble sampling routines. IR contains the user RPL programs SAMPLE and PLAYBACK and the machine code objects IRSAMP and IRPLAY. IR2 contains SAMPLE2, PLAYBACK2, IRSAMP2, and IRPLAY2. Similarly, irsamp.star and irplay.star are the STAR source for the 3-nibble sampling/playback routines, while irsamp2.star and irplay2.star are the source for the 2-nibble routines. The program SAMPLE (SAMPLE2) will take either a real number in level 1, which is used to generate a string of that length to receive the sample, or a string which will be overwritten with sample data. It calls the machine-language program IRSAMP (IRSAMP2) which performs the sampling. IRSAMP checks for a string object in level 1, which must have SIZE > 1, and aborts if it doesn't find one. It then waits up to 15 seconds for IR input, (that is, for you to place your remote control next to the calculator and press the button for the remote function you want to sample) and aborts if none is received in that time. Otherwise it begins sampling and exits when the end of the string in level 1 is reached. I have found that holding an IR remote too close to the calculator during sampling will often result in ineffective samples; I get best results with the remote about 5-10 cm from the IR input port. The program PLAYBACK (PLAYBACK2) will take a string in level 1 and feed it to IRPLAY (IRPLAY2), then drop the string. You can feed strings directly to IRPLAY if you wish, but they will be left on the stack (although this is a useful way to test samples without having to recover them with LASTARG). You should only feed strings created with IRSAMP to PLAYBACK or IRPLAY. It is possible to create strings which leave the HP-48 IR LED on for long periods of time, which drains the batteries and may cause hardware damage. In any case, IRPLAY will turn the IR LED off before exiting. Two of my friends who have tested these programs have reported that they have experienced crashes while using them, although one report did not appear to involve memory corruption or any other damage. Therefore, I do not guarantee these programs to be bug-free--they may cause crashes, memory corruption, or even hardware damage if used improperly, although I can also say that I have had no problems for over a week since I debugged the routines in the IR directory. Neither are they guaranteed to work with any IR remote control, although I suspect they will have greater success than previous remote sampling programs. I would like to thank Dave Marsh for his original IR sampling programs, which I have copied small parts of and which were my main source of technical information in writing these programs, and Jan Brittenson for his excellent STAR assembler and MLDL debugger which made writing and debugging these programs easy. ---------- BEGIN_SRC irsamp.star ;irsamp.star: ML core of a learning remote control sampler using run-length ;encoding for samples. This version uses a 2-nibble repeat count. ;requires a string in stack level 1, and overwrites its contents with the ;sample data. header `x' code move.a @d1, a ;put TOS pointer in a call save_regs ;save RPL registers call #01115 ;disable interrupts call #01bbd ;turn off display move.a a, d1 ;put TOS obj pointer in d1 move.a @d1, a ;get obj prolog move.p5 type_string, c ;get string prolog brne.a c, a, bailout ;if not a string prolog abort add 5, d1 ;move past string prolog move.a @d1, c ;get string length field add 5, d1 ;d1 now points to string data sub.a 5, c ;subtract 5 to get length of chars move.a c, b div3: srb.a c ;divide c by 4 srb.a c add.a c, b ;add to b brnz.a c, div3 ;while c > 0 srb.a b ;divide b by 4, to get approx. c/3 srb.a b ;c.a is 0 inc.a c ;c.a is 1 brle.a b, c, bailout ;if b <= 1, no room for samples dec.a b ;trust me, you need this move.5 #0011a, d0 ;have d0 point to IR LED input nib clr.a c move.1 c, @d0 ;clear LED status move.p5 #80000, c ;move timeout count to c ;should last about 16 s wait: dec.a c ;c is timeout counter brcs bailout ;if we dec past 0, bail out checkled: move.xs @d0, a ;otherwise, check IR LED input brbc 8, a, wait ;if no input, wait for it sample: clr.b c ;c.b is the repeat count move.xs a, c ;copy current input state from a.xs samploop: move.xs @d0, a ;get IR LED status inc.x c ;increment repeat count breq.xs c, a, samploop ;while c.xs is undisturbed, loop move.3 c, @d1 ;write state and repeat count add 3, d1 ;increment d1 dec.a b ;one less sample brcc sample ;back for new sample bailout: call #010e5 ;allow interrupts call #01b8f ;turn on display jump rr_rplcont ;back to RPL endcode END_SRC irsamp.star BEGIN_SRC irplay.star ;irplay.star: ML core of playback program for learning remote control ;requires a string in stack level 1 generated by irsamp header `x' code move.a @d1, a ;put TOS obj pointer in a call save_regs ;save RPL registers call #01115 ;disable interrupts call #01bbd ;turn off display move.a a, d1 ;put TOS obj pointer in d1 move.a @d1, a ;get obj prolog move.p5 type_string, c ;get string prolog brne.a c, a, bailout ;if not a string prolog abort add.a 5, d1 ;move past string prolog move.a @d1, c ;get string length field add.a 5, d1 ;d1 now points to string data sub.a 5, c ;subtract 5 for length of string chars move.a c, b div3: srb.a c ;divide c by 4 srb.a c add.a c, b ;add to b brnz.a c, div3 ;while c > 0 srb.a b ;divide b by 4, to get approx. c/3 srb.a b ;c.a is 0 inc.a c ;c.a is 1 brle.a b, c, bailout ;if b <= 1, no room for samples dec.a b ;trust me, you need this move.5 #0011c, d0 ;d0 points to IR LED output playback: move.3 @d1, c ;get a sample add 3, d1 dec.x c ;decrement repeat count move.xs c, a ;copy IR state to a playloop: move.xs c, @d0 ;output current LED state dec.x c ;decrement counter breq.xs c, a, playloop ;timing only-branch never taken dec.a b ;one less sample brcc playback ;repeat until out of samples clr.a c ;clear c.0 move.1 c, @d0 ;clear LED output bailout: call #010e5 ;allow interrupts call #01b8f ;turn on display jump rr_rplcont ;back to RPL endcode END_SRC irplay.star BEGIN_SRC irsamp2.str ;irsamp2.star: ML core of a learning remote control sampler using run-length ;encoding for samples. This version uses a one-nibble repeat count. ;requires a string in stack level 1, and overwrites its contents with the ;sample data. header `x' code move.a @d1, a ;put TOS pointer in a call save_regs ;save RPL registers call #01115 ;disable interrupts call #01bbd ;turn off display move.a a, d1 ;put TOS obj pointer in d1 move.a @d1, a ;get obj prolog move.p5 type_string, c ;get string prolog brne.a c, a, bailout ;if not a string prolog abort add 5, d1 ;move past string prolog move.a @d1, c ;get string length field add 5, d1 ;d1 now points to string data sub.a 5, c ;subtract 5 to get length of chars move.a c, b srb.a b ;divide string length by two clr.a c inc.a c ;set c.a to 1 brle.a b, c, bailout ;if b <= 1, no room for samples dec.a b ;trust me, you need this move.5 #0011a, d0 ;have d0 point to IR LED input nib move.p5 #80000, c ;move timeout count to c move 1, p clr.a a move.b a, @d0 ;clear IR status nibble wait: dec.a c ;c is timeout counter brcs bailout ;if we dec past 0, bail out move.b @d0, a ;otherwise, check IR LED input brbc 4, a, wait ;if no input, wait for it sample: clr.b c ;c.0 is the repeat count move.p a, c ;copy current input state from a.1 samploop: move.b @d0, a ;get IR LED status inc.b c ;increment repeat count breq.p c, a, samploop ;while c.1 is undisturbed, loop move.b c, @d1 ;write state and repeat count add 2, d1 ;increment d1 dec.a b ;one less sample brcc sample ;back for new sample bailout: move 0, p call #010e5 ;allow interrupts call #01b8f ;turn on display jump rr_rplcont ;back to RPL endcode END_SRC irsamp2.star BEGIN_SRC irplay2.star ;irplay2.star: ML core of playback program for learning remote control ;requires a string in stack level 1 generated by irsamp2 header `x' code move.a @d1, a ;put TOS obj pointer in a call save_regs ;save RPL registers call #01115 ;disable interrupts call #01bbd ;turn off display move.a a, d1 ;put TOS obj pointer in d1 move.a @d1, a ;get obj prolog move.p5 type_string, c ;get string prolog brne.a c, a, bailout ;if not a string prolog abort add.a 5, d1 ;move past string prolog move.a @d1, c ;get string length field add.a 5, d1 ;d1 now points to string data sub.a 5, c ;subtract 5 for length of string chars move.a c, b srb.a b ;divide string length by two clr.a c inc.a c ;set c.a to 1 brle.a b, c, bailout ;if b <= 1, no room for samples dec.a b ;trust me, you need this move.5 #0011b, d0 ;d0 points to IR LED output - 1 clr.a a move 1, p playback: move.b @d1, c ;get a sample add 2, d1 dec.b c ;predecrement c move.p c, a ;copy IR state to a playloop: move.b a, @d0 ;output current LED state dec.x c ;decrement counter breq.p c, a, playloop ;while c.1 is unchanged, loop dec.a b ;one less sample brcc playback ;repeat until out of samples move 0, p clr.a c ;clear c.0 move.b c, @d0 ;clear LED output bailout: call #010e5 ;allow interrupts call #01b8f ;turn on display jump rr_rplcont ;back to RPL endcode END_SRC irplay2.star BEGIN_ASC ir.asc %%HP: T(3)A(R)F(.); "69A20FF7C32000000060942505C4149560CCD204A0001438FB97608F511108FD BB1013114334C2A208A626174147174818FA4D5819F2819F2C18AE1F819F1819 F1E68BDF21BC1100CD15F2172A3EAAA1542A3E9226FCD54ED215C08F5E0108FF 8B108D341509B0006094253514D40560CCD20BB0001438FB97608F511108FDBB 1013114334C2A208A697174147174818FA4D5819F2819F2C18AE1F819F1819F1 E68BD641BA1100D215C03400008CE4D21522808682FCDAE2AA61522B369226F1 5D2172CD54E8F5E0108FF8B108D341500D0008005C41495241434B480D9D20E1 6323CE2278BF168BC1ED2A2D9AE1AFE22D9D20C2A203200035472796E6760256 87075636475646933A1B21305DF2284E2060942505C414958DBF193632B2130A 9000603514D405C45460D9D20E1632D8732D9D2078BF168BC14B2A2279E18A73 2D9D20E4A20510007DC8100000000000E25A1E4A20510006765400000000000E 25A1B21305DF2278BF168BC1ED2A2D9AE18A732D9D20C2A2013000255616C602 F6270235472796E676C20207C656163756933A1B21305DF22B21305DF2284E20 6094253514D40593632B2130BF43" END_ASC ir.asc BEGIN_UUE ir.uue begin 644 ir3 M2%!(4#0X+466*O!_/`(````&25)03$%9!LPM0`H`08._>0;X%1&`W[L!,1$T M0RPJ@&IB<11T<82!K]2%D2\8^<*!ZO$8^8&1'VZX_1++$0#<42]QHN.J&D6B MXREBSUWD+5$,^.40@/^X`=A#49`+``9)4E-!35`&S"VP"P!!@[]Y!O@5$8#? MNP$Q$31#+"J`:GEQ%'1QA(&OU(61+QCYPH'J\1CY@9$?;KAM%*L1`"U1#$,` M`,A.+5$B"&@HSZTNJA8ELF,I8A_5$B?<18Y?#@'XCQN`/10%T`"``,44E"44 M-+2$T-D"'C8R["*'^V&X'-ZBTJD>^B[2V0(L*C`"`%-T'!E8W1E M9#FCL1(#U2^"Y`(&25)03$%9V/N18R,K,:`)``9304U03$4&G2W@82.--]+9 M`H?[8;@&D`A4`8&=%``````#@ M4AHK,5#](H?[8;@8"^.40@/^X`=A#4>`+``E03$%90D%#2S()G2W@82/#+G*X'X;+ MX2TJG>JA[R*=+<"B`B,`,$4GE^9V!E*&!U`'`P%=0$Q50D<]#9`AXVTG@CG2UPN!^&RT$K*G+I@7HC MG2W@I`(5`'#-&```````X%(:3BI0`0!V5@0``````"ZEL1(#U2]RN!^&R^$M M*IWJ@7HCG2W`H@(Q`"!5%L8&\B8',D4GE^9VQ@("QU86-E>6,QHK,5#](BLQ 34/TB2"YPD"0U%=0$)9-C(RLQ```` ` end END_UUE ir2.uue