@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`  R@P!( L(1   Y I`  d  Ld M * @  $ % CC$$)%1 Udߥ$9%: !0 S$% DD˙`  }J)Lr d M * @  $ % CC$$)%1 Udߥ$9%: !0 S$%} DD˙`  }J)Lr J  ((  p L ()   J}L= ( L 0q A    IB JC;? D W } LL  ` W )LA!  ߰")-݆ p" } $G@LL 08`Q")<2Q0 -G$Ș݆ UL# ; p8(()(0ʥ)NQ` }$GȘ݆LU )L ݆ L GȘ ݆LL )W>Z   HH)H }p h  hyhy D L> L JJ    ! LA*` BF }7'8  M HN H` 8 Z  \LdJJ!"! GFE@F (!L }EE !E^ ^ E E7EȩEdE/EȩE  D } .L }  ;F d  ;?F7F? ( .   Z D LL d } . D  L    p  E` , d)  D L) 0BM݊L݉} ML  N݆ L NLML [ TEqEHȱEqEh 0Gȹ G} HLL GɛL  LFREE SECTORS G) *Gȩ GȽG GȌ*jj >G} C8jJ3j2CD( C202C ԠBX` N 1? l LlD:RAMDISK}.COMLu L1 L ;LHL  T`  `1  ɐ     `TU  } L ? .  t`GBJ ~DEHI B V0dV!}QDEHI VF9 ,0 ,0 s0hhL  L` H hDHEh"}DEL8HI4 0 HI,0 0  9 .G VLO#},0 L4*IJ`llD1:AUTORUN.SYSNEED MEM.SAV TO LOAD THIS FILE.D1:MEM.SAV J y08 B|DEHI$} V0 0`B;DEL`?<0LV`@ʆ v s? F0Ξ05: [ BDEHI%} VY8 B V  @  /DE `E:D1:DUP.SYSERROR-SAVING USER MEMORY ON DISKTYPE Y TO &}STILL RUN DOS B;DE J  (` 9 V⪍ ઍ  -'}LLu ÝDEHILV 9 .l 9 .l  `` s$B BH(}I|DE V BLV nB,DE JLV B V BLVDEIʩ BꭝLu  } 3E:}DISK OPERATING SYSTEM II VERSION COPYRIGHT 1984 ATARI CORP.A. DISK DIRECTORY I. FORMAT DISKB. RUN CARTRIDG*}E J. DUPLICATE DISKC. COPY FILE K. BINARY SAVED. DELETE FILE(S) L. BINARY LOADE. RENAME FILE M. RUN AT ADDRES+}SF. LOCK FILE N. CREATE MEM.SAVG. UNLOCK FILE O. DUPLICATE FILEH. WRITE DOS FILES P. FORMAT SINGLEL !N',}#"&))9(&*)/h)''-&؆莟R'S  vL/ˢ L }Insert DOS 2.0s, type Y Λx -}DEfHI 1莏#q! @ y0ɛ8A0,' ȅ 1 1ild! 1L!NO SUCH ITEMSELECT.} ITEM OR FOR MENU! 0 .z:*{}.|{ 1 0 0JB 18L%|DL/}%DIRECTORY--SEARCH SPEC,LIST FILE?[# 0 0 &|D3" 1L!NOT A DISK FILEN !B 1L!E# 1 !BD0}ED:}:1BJ|DE 1DEBHI 1 h0ߢ 0.1}  0?詛 1 y0YЛ 1 ;#L" ;#L! BL1TYPE "Y" TO DELETE...DELETE FILE SPEC2}COPY--FROM, TO?OPTION NOT ALLOWED736 FREE SECTORS COPYING---D1:DIRECK.COMl# 0|D .L/%#3}##JB|DE 1BHID#E 1#0: B 1L!#͑### B 1#c$0SY4}S1}:## # # .#Ƚ# # 𩛙## 1,#PD#ELJ- <.BJD#E 5}1 1HH 0hh|DL%1}:̳# L% #D#EL% 1 0 . .0O% 1L!WILD CARDS NOT A6}LLOWED IN DESTINATION 0 <.|K}N 2 FORMAT. t* 5) 1L!`) 0NΞ 0 L1) 1 L!BAD LOAD FILELOAD FROM WHAT FILE?) 0 ?}0#B 1L!WHAT FILE TO LOCK?) 0 0$B 1L!WHAT FILE TO UNLOCK?DUP DISK-SOURCE,DEST DRIVES?TYPE "Y" IF OK TO US@}E PROGRAM AREACAUTION: A "Y" INVALIDATES MEM.SAV.FE! +L1   `*  70 2 2A} 0.* 1 y0 0)INSERT BOTH DISKS, TYPE RETURN^, 1 y038逍 N, 1L! ,B}C, t*  Lx+, 0 ^, 1 y0 , ,0,0 ,L+ ,I0 ,Vǭ0C}Ξ, 0 }, 1 y0C,ШC, 0K'!" H H 'h h Lx+!EF 5L1L!D,I,HhD}` NOT ENOUGH ROOMINSERT SOURCE DISK,TYPE RETURNINSERT DESTINATION DISK,TYPE RETURNE}`  `8 rL1`-* 1P* 1 y0Y`hhL!NAME OF FILE TO MOVE?- 0 0|DL% <.F},^ 1 70 0 .@L# .BJ 1  DEHIB V L1 ,} 1 70,L.  G}JB|,#P#DE 1 HI BDEHHII 1 B 1 ,^ 1 70,0La- B V,#PH},^ 1 70 0L#L!-* 1P* 1 y0Yj383}mm ݭI}}`8}``|* ? ɛ,`|:-)| / 1L!`DESTINATION CANT BE DOJ}S.SYS0 0H{ 24Δ 28/L!/) 2 Π 2 0 ξK}hAΞB,0 J 1 BDEHI,HÝDE 1HIHIDELSAVE-GIVE L}FILE,START,END(,INIT,RUN)O S0 1`BDEPHI V` S0H 1 L!M}0 0 1L~0`PLEASE TYPE 1 LETTER,0`hhL! 70 1L0L<1 ,;ɛ7,"ɛ:ݦ1ݥN}A"D|ݤD|ȩ:|ȩ|ɛ,,(/+.ީ1 1,ɛ`轤{NAMEO} TOO LONG B VL!` L1I H1EΝDL1|mDiE` V0`8d/8 i:222 1 LP}!ERROR- 138ɛ+,' 20*.. өr2 1``2TOO MANY DIGITSINVALID HEXAQ}DECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8uR} ECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8u%!PS-Adobe-2.0 %%Title: /tmp/xfig-fig018505 %%Creator: fig2dev Version 2.1.8 Patchlevel 1 %%CreationDate: Tue Apr 26 07:44:46T} 1994 %%For: deaven@ishmael.ameslab.gov (David Deaven) %%Orientation: Landscape %%BoundingBox: 85 237 526 554 %%Pages: 1 %%EnU}dComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /l {lineto} bind def /m {moveto} bind def /s {sV}troke} bind def /n {newpath} bind def /gs {gsave} bind def /gr {grestore} bind def /clp {closepath} bind def /graycol {dup duW}p currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul setrgbcolor} bind def /col-1 {} def /col0 {0 0 0 setrgbcolor} binX}d def /col1 {0 0 1 setrgbcolor} bind def /col2 {0 1 0 setrgbcolor} bind def /col3 {0 1 1 setrgbcolor} bind def /col4 {1 0 0 sY}etrgbcolor} bind def /col5 {1 0 1 setrgbcolor} bind def /col6 {1 1 0 setrgbcolor} bind def /col7 {1 1 1 setrgbcolor} bind defZ} /col8 {.68 .85 .9 setrgbcolor} bind def /col9 {0 .39 0 setrgbcolor} bind def /col10 {.65 .17 .17 setrgbcolor} bind def /col1[}1 {1 .51 0 setrgbcolor} bind def /col12 {.63 .13 .94 setrgbcolor} bind def /col13 {1 .75 .8 setrgbcolor} bind def /col14 {.7 \}.13 .13 setrgbcolor} bind def /col15 {1 .84 0 setrgbcolor} bind def /DrawEllipse { /endangle exch def /startangle exch def]} /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y translate xrad yrad scale^} 0 0 1 startangle endangle arc savematrix setmatrix } def end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} d_}ef /$F2psEnd {$F2psEnteredState restore end} def %%EndProlog $F2psBegin 0 setlinecap 0 setlinejoin 72.5 228.5 translate 90 r`}otate 0.900 -0.900 scale 0.500 setlinewidth % Polyline n 99 224 m 99 207 l 90 204 l 108 200 l 90 196 l 108 191 l 90 187a} l 108 182 l 90 178 l 99 175 l 99 162 l gs col-1 s gr % Polyline n 99 346 m 99 329 l 90 326 l 108 322 l 90 318 l 108 b}313 l 90 309 l 108 304 l 90 300 l 99 297 l 99 284 l gs col-1 s gr % Polyline n 99 282 m 99 265 l 90 262 l 108 258 l c}90 254 l 108 249 l 90 245 l 108 240 l 90 236 l 99 233 l 99 220 l gs col-1 s gr % Polyline n 99 409 m 99 384 l gs col-1d} s gr % Polyline n 89 384 m 109 384 l gs col-1 s gr % Polyline n 89 374 m 109 374 l gs col-1 s gr % Polyline n 99 374 m 99 34e}9 l gs col-1 s gr % Polyline n 99 469 m 99 489 l gs col-1 s gr % Polyline n 79 489 m 119 489 l gs col-1 s gr % Polyline n 84 f}494 m 114 494 l gs col-1 s gr % Polyline n 94 504 m 104 504 l gs col-1 s gr % Polyline n 89 499 m 109 499 l gs col-1 s gr % Pg}olyline n 174 424 m 163 436 l gs col-1 s gr n 169.880 431.454 m 163.000 436.000 l 166.931 428.751 l gs 2 setlinejoin col-1 s h}gr % Polyline n 177 433 m 166 445 l gs col-1 s gr n 172.880 440.454 m 166.000 445.000 l 169.931 437.751 l gs 2 setlinejoin coi}l-1 s gr % Polyline n 289 319 m 289 339 l gs col-1 s gr % Polyline n 269 339 m 309 339 l gs col-1 s gr % Polyline n 274 344 mj} 304 344 l gs col-1 s gr % Polyline n 284 354 m 294 354 l gs col-1 s gr % Polyline n 279 349 m 299 349 l gs col-1 s gr % Polyk}line n 199 409 m 199 469 l gs col-1 s gr % Polyline n 208 443 m 190 443 l gs col-1 s gr % Polyline n 208 426 m 190 426 l 199l} 443 l 208 426 l gs 0.00 setgray fill gr gs col-1 s gr % Polyline n 199 424 m 199 407 l 190 404 l 208 400 l 190 396 l 20m}8 391 l 190 387 l 208 382 l 190 378 l 199 375 l 199 362 l gs col-1 s gr % Ellipse n 59 469 5 5 0 360 DrawEllipse gs 0.0n}0 setgray fill gr gs col-1 s gr % Ellipse n 209 154 5 5 0 360 DrawEllipse gs 0.00 setgray fill gr gs col-1 s gr % Ellipse n 3o}29 154 5 5 0 360 DrawEllipse gs 0.00 setgray fill gr gs col-1 s gr % Ellipse n 59 119 5 5 0 360 DrawEllipse gs 0.00 setgray fp}ill gr gs col-1 s gr % Ellipse n 289 329 3 3 0 360 DrawEllipse gs 0.00 setgray fill gr gs col-1 s gr % Ellipse n 99 469 3 3 0q} 360 DrawEllipse gs 0.00 setgray fill gr gs col-1 s gr n 116.000 251.000 m 108.000 249.000 l 116.000 247.000 l gs 2 setlinejor}in col-1 s gr % Polyline n 108 249 m 149 249 l gs col-1 s gr % Polyline n 99 389 m 99 469 l gs col-1 s gr % Polyline n 99 119s} m 99 169 l gs col-1 s gr % Polyline n 99 269 m 99 289 l gs col-1 s gr % Polyline n 99 329 m 99 369 l gs col-1 s gr % Polylint}e n 349 309 m 349 189 l 269 189 l 269 309 l clp gs col-1 s gr % Polyline n 249 309 m 249 189 l 149 189 l 149 309 l clp u}gs col-1 s gr % Polyline n 99 119 m 289 119 l 289 189 l gs col-1 s gr % Polyline n 169 119 m 169 189 l gs col-1 s gr % Polylv}ine n 209 154 m 209 189 l gs col-1 s gr % Polyline n 329 154 m 329 189 l gs col-1 s gr % Polyline n 59 119 m 99 119 l gs col-w}1 s gr % Polyline n 159 309 m 159 339 l 99 339 l gs col-1 s gr % Polyline n 179 309 m 179 339 l 154 339 l gs col-1 s gr % Px}olyline n 199 309 m 199 369 l gs col-1 s gr % Polyline n 59 469 m 289 469 l 289 389 l 349 389 l gs col-1 s gr % Polyline n y}219 309 m 219 329 l 289 329 l gs col-1 s gr % Polyline n 289 309 m 289 324 l gs col-1 s gr % Polyline n 354 389 m 354 369 l z} 349 369 l 349 389 l clp gs col-1 s gr % Polyline n 199 369 m 319 369 l 329 379 l 339 369 l gs col-1 s gr % Polyline n 31{}9 309 m 319 329 l 289 329 l gs col-1 s gr /Times-Roman findfont 12.00 scalefont setfont 19 474 m gs 1 -1 scale (GND) col-1 |}show gr /Times-Roman findfont 12.00 scalefont setfont 64 254 m gs 1 -1 scale (20k) col-1 show gr /Times-Roman findfont 12.00}} scalefont setfont 49 384 m gs 1 -1 scale (470pF) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 64 319 m gs 1~} -1 scale (22k) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 59 194 m gs 1 -1 scale (2.2k) col-1 show gr /Tim}es-Roman findfont 12.00 scalefont setfont 289 249 m gs 1 -1 scale (GP1U52X) col-1 show gr /Times-Roman findfont 12.00 scalef}ont setfont 199 249 m gs 1 -1 scale (555) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 9 124 m gs 1 -1 scale} (+5VDC) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 324 409 m gs 1 -1 scale (EXT IR) col-1 show gr /Times-R}oman findfont 12.00 scalefont setfont 216 436 m gs 1 -1 scale (IR LED) col-1 show gr /Times-Roman findfont 12.00 scalefont s}etfont 164 394 m gs 1 -1 scale (150) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 287 205 m gs 1 -1 scale (2}) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 327 204 m gs 1 -1 scale (1) col-1 show gr /Times-Roman findfon}t 12.00 scalefont setfont 286 301 m gs 1 -1 scale (3) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 216 300 m } gs 1 -1 scale (1) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 197 300 m gs 1 -1 scale (3) col-1 show gr /Ti}mes-Roman findfont 12.00 scalefont setfont 176 300 m gs 1 -1 scale (6) col-1 show gr /Times-Roman findfont 12.00 scalefont s}etfont 157 300 m gs 1 -1 scale (2) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 159 253 m gs 1 -1 scale (7) }col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 166 205 m gs 1 -1 scale (8) col-1 show gr /Times-Roman findfont }12.00 scalefont setfont 206 205 m gs 1 -1 scale (4) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 305 302 m g}s 1 -1 scale (CASE) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 201 144 m gs 1 -1 scale (TX) col-1 show gr /}Times-Roman findfont 12.00 scalefont setfont 320 142 m gs 1 -1 scale (RX) col-1 show gr /Times-Roman findfont 12.00 scalefon}t setfont 169 264 m gs 1 -1 scale (\(RS276-1723\)) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 279 264 m gs} 1 -1 scale (\(RS276-137\)) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 212 452 m gs 1 -1 scale (\(RS276-143}\)) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 14 400 m gs 1 -1 scale (\(RS272-125\)) col-1 show gr % Ellip}se n 247 45 4 4 0 360 DrawEllipse gs col-1 s gr % Ellipse n 267 45 4 4 0 360 DrawEllipse gs col-1 s gr % Ellipse n 287 45 4 4} 0 360 DrawEllipse gs col-1 s gr % Ellipse n 307 45 4 4 0 360 DrawEllipse gs col-1 s gr % Ellipse n 327 45 4 4 0 360 DrawElli}pse gs col-1 s gr % Ellipse n 257 65 4 4 0 360 DrawEllipse gs col-1 s gr % Ellipse n 277 65 4 4 0 360 DrawEllipse gs col-1 s }gr % Ellipse n 297 65 4 4 0 360 DrawEllipse gs col-1 s gr % Ellipse n 317 65 4 4 0 360 DrawEllipse gs col-1 s gr % Polyline n} 232 35 m 342 35 l gs col-1 s gr % Polyline n 247 75 m 327 75 l gs col-1 s gr % Polyline n 232 35 m 247 75 l gs col-1 s gr % }Polyline n 342 35 m 327 75 l gs col-1 s gr % Polyline n 267 85 m 277 65 l gs col-1 s gr n 271.633 71.261 m 277.000 65.000 l 2}75.211 73.050 l gs 2 setlinejoin col-1 s gr % Polyline n 317 85 m 297 65 l gs col-1 s gr n 301.243 72.071 m 297.000 65.000 l }304.071 69.243 l gs 2 setlinejoin col-1 s gr % Polyline n 217 40 m 247 45 l gs col-1 s gr n 239.438 41.712 m 247.000 45.000 l} 238.780 45.658 l gs 2 setlinejoin col-1 s gr % Polyline n 237 80 m 257 65 l gs col-1 s gr n 249.400 68.200 m 257.000 65.000 }l 251.800 71.400 l gs 2 setlinejoin col-1 s gr /Times-Roman findfont 12.00 scalefont setfont 252 100 m gs 1 -1 scale (+5VDC)} col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 307 100 m gs 1 -1 scale (GND) col-1 show gr /Times-Roman findfo}nt 12.00 scalefont setfont 171 88 m gs 1 -1 scale (RX \(TRIG0\)) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont} 172 43 m gs 1 -1 scale (TX \(A0\)) col-1 show gr /Times-Roman findfont 12.00 scalefont setfont 233 27 m gs 1 -1 scale (MAL}E \(COMPUTER\)) col-1 show gr % Polyline n 144 54 m 144 14 l 14 14 l 14 54 l clp gs col-1 s gr /Times-Roman findfont 12.00} scalefont setfont 19 29 m gs 1 -1 scale (IRG circuit version 0.1) col-1 show gr /Times-Roman findfont 12.00 scalefont setfo}nt 19 47 m gs 1 -1 scale (David Deaven) col-1 show gr showpage $F2psEnd show gr /Times-Roman findfont 12.00 scalefont setfoI/* irg.h: CC65 functions for the infrared gateway (IRG) Version 1.0 ; ------------------------------------------------------- }----------- ; Copyright 1994 David Deaven version 1.0 ; Permission to use, copy, and distribute this code is granted ; provid }ed that it is not used for commercial applications. ; deaven@iastate.edu */ #ifndef _IRG_H_ #define _IRG_H_ int IRGinit(/* s }ample, ton, toff, repeat, tonmin, toffmax, qtime, totime */); int IRGread(/* char *buffer, int size */); int IRGwrite(/* char } *buffer */); #endif /* _IRG_H_ */ ffmax, qtime, totime */); int IRGread(/* char *buffer, int size */); int IRGwrite(/* char $; irg.m65: CC65 functions for the infrared gateway (IRG) Version 0.1 ; ------------------------------------------------------}------------ ; Copyright 1994 David Deaven version 0.1 ; Permission to use, copy, and distribute this code is granted ; provi}ded that it is not used for commercial applications. ; David Deaven -- deaven@iastate.edu ; ; This ra65 library package provi}des access to an infrared gateway, ; or IRG, connected to an Atari 400/800/XL/XE 8-bit computer. A ; description of how to b}uild the IRG circuit, which simply plugs into ; a joystick port, can be found in the file README.HARDWARE included ; with th}is distribution. The functions defined here are: ; ; void IRGinit(int sample, int ton, int toff, int repeat, ; int tonmin,} int toffmax, int qtime, int totime) ; int IRGread(char *buffer, int size) = # bytes returned ; int IRGwrite(char *buffer) = }0, or 1 if IRG is active ; ; See the file README for more information, and the C program ; irgdemo.c which demonstrates the u}se of these functions. ; ------------------------------------------------------------------ rdblen = 128 ; internal read buff}er length (<256) ; Some device things that the standard CC65 headers don't have PACTL = $D302 PORTA = $D300 TRIG0 = $D010 GR}ACTL = $D01D ; ------------------------------------------------------------------ ; Start the vertical blank service routine} and set parameters. ; ; void IRGinit(int sample, int ton, int toff, int repeat, ; int tonmin, int toffmax, int qtime, int }totime) ; _irginit: jsr enterfun ; get all arguments ldy #16 jsr ldaxysp sta sample ldy #14 jsr ldaxysp sta ton ldy #}12 jsr ldaxysp sta toff ldy #10 jsr ldaxysp sta repeat ldy #8 jsr ldaxysp sta tonmin ldy #6 jsr ldaxysp sta toffma}x ldy #4 jsr ldaxysp sta qtime ldy #2 jsr ldaxysp sta totime LDA #%00111001 ; set up PIA STA PACTL ; output bit A0 }LDA #%00000001 STA PORTA LDA #%00111101 STA PACTL LDA #0 ; turn IRG output off STA PORTA LDA #0 STA nread ; clear re}ad buffer sta nwrite sta rdbuf sta irgstat ; no invalid events LDA #6 ; new immediate VBLANK LDX #VImm^ LDY #VImm\ J}SR SETVBV LDA #7 ; new deferred VBLANK LDX #VBlank^ LDY #VBlank\ JSR SETVBV jmp exitfun ; -----}------------------------------------------------------------- ; Read the IRG buffer safely into a user buffer. ; ; int IRGrea}d(char *buffer, int size) = # bytes returned ; _irgread: jsr enterfun ldy #2 ; get arguments jsr ldaxysp sta blen ldy #}4 jsr ldaxysp jsr psave sta ptr1 ; set to point at buffer stx ptr1+1 LDX nread ldy #0 ; # bytes transferred fine: cp}x nwrite ; end of buffer? beq rddone LDA rdbuf,x ; transfer one byte STA (ptr1),Y iny INX CPX #rdblen BNE skip1 ldx #}0 skip1: cmp #0 ; end of buffer? bne skip2 dey ; zero byte is meaningless, remove jmp rddone skip2: cpy blen ; buffer} overflow? bmi fine rddone: stx nread ; update next read position tya ; return # bytes ldy irgstat ; bad buffer? beq rd}do2 lda #0 rddo2: ldx #0 jsr prest jmp exitfun ; ------------------------------------------------------------------ ; Se}nd a buffer out (null-terminated string). ; ; int IRGwrite(char *buffer) = 0, or 1 if IRG is active ; _irgwrite: jsr enterfu}n ldy #2 jsr ldaxysp jsr psave sta ptr1 stx ptr1+1 LDA CRITIC ; is anything else BEQ ok2 ; going on? ldax #1 ; if so}, don't send jsr prest jmp exitfun ok2: JSR IStop ; stop DMA etc. lda repeat sta nwr wr0: LDY #$FF LDX #8 loop: INY LD}A (ptr1),Y BEQ eot STA bytbuf sloop: LDA #0 ROL bytbuf ROL A STA PORTA TXA LDX ton loop1: JSR DELAY DEX BNE loop1 }STX PORTA LDX toff loop0: JSR DELAY DEX BNE loop0 TAX DEX BNE sloop LDX #8 BNE loop eot: ldx qtime eot8: jsr delay } dex bne eot8 dec nwr bne wr0 JSR IStart ; restart DMA etc ldax #0 jsr prest jmp exitfun nwr: .byte 0 ; -------------}----------------------------------------------------- ; Immediate vertical blank code. Unlike the Atari OS code, if CRITIC i}s ; set, _nothing_ gets done. This state should not be maintained too ; long, but for the length of an IR packet it's OK. ; }VImm: LDA CRITIC BEQ cont JMP XITVBV ; outta here cont: JMP $E45F ; OS Stage 1 ; -----------------------------------------}------------------------- ; Deferred vertical blank code. Examine TRIG0 for new IR input, ; catch all input by keeping TRIG0} in hardware latch mode. When TRIG0 has ; been low, display DMA is turned off, CRITIC is enabled, and this routine ; becomes} the "mainline" code with the interrupt return info still on the ; stack. An attempt is made to read a valid code into the bu}ffer, then ; control is returned to the interrupted code. ; VBlank: LDA CRITIC BNE leave ; never happens? LDA TRIG0 BEQ re}c ; IRG has been active LDA #%100 STA GRACTL ; set TRIG0 latch leave: JMP XITVBV ; outta here rec: JSR IStop LDA #0} STA GRACTL ; clear TRIG0 latch still: LDX qtime ; detect record gap LDA #1 ; IR input bit is LSB wait: JSR Delay BIT} TRIG0 BEQ still ; (input not quiet) DEX BNE wait ; we'll wait as long as it takes! LDY totime ; looking for a "1" bit t}o start retry: LDX qtime mark: BIT TRIG0 BEQ st0 ; got "1", go for it JSR Delay DEX BNE mark DEY BNE retry JMP ex}it ; time-out, no harm done st0: LDY #8 ; bit counter start: LDX #0 wton: JSR Delay INX BIT TRIG0 BEQ wton CPX t}onmin ; bit long enough? BPL okbit LDA #1 ; bad "1" bit STA irgstat JMP exit okbit: SEC ; store a "1" bit JSR store } LDX #0 ; wait for "0" to end wtoff: JSR Delay INX BEQ eott ; never? forced EOT (very long "0") BIT TRIG0 BNE wtoff CP}X qtime ; the space is EOT? BPL eott CPX toffmax ; a "0" bit? BMI start ; normal space CLC ; store a "0" bit JSR store } JMP start eott: CPY #8 ; normal EOT BEQ done ; last data byte has been written CLC JSR store ; pad buffer w/zeroes J}MP eott done: ldy #8 ; terminate buffer with zero pad: clc jsr store cpy #8 bne pad LDA #0 STA irgstat ; normal ope}ration JMP exit ; ------------------------------------------------------------------ ; Store bits MSB to LSB in memory at r}dbuf ; ; C = bit (0/1) ; X = not saved ; Y = #bits in bytbuf (0-7), 8==0 ; A = saved ; store: ROL bytbuf ; store byte pre-bu}ffer DEY BEQ byte RTS byte: TAX ; save A LDA bytbuf LDY nwrite STA rdbuf,Y INY cpy #rdblen bne byte1 ldy #0 byte}1: cpy nread ; buffer full? beq over sty nwrite LDY #8 ; new byte TXA RTS over: dey ; back off one cpy #$ff bne ove}r1 ldy #rdblen dey over1: lda #0 sta rdbuf,y ; insert artificial terminator sty nwrite PLA ; pop "jsr store" ret}urn address PLA LDA #2 ; buffer overrun... STA irgstat ; ...fall through to exit exit: JSR IStart ; restart DMA etc. }JMP XITVBV ; outta here ; ------------------------------------------------------------------ ; Wait one delay time, saving A}, X, Y ; time = (20+5*sample) clock pds ; Delay: PHA ; 3 cycles TXA ; 2 LDX sample ; 3 dloop: DEX ; 2 BNE dloop ; 3 }TAX ; 2 PLA ; 4 RTS ; 6 ; ------------------------------------------------------------------ IStop: LDA #0 STA DMACTL} ; prevent DMA LDA #1 STA CRITIC RTS IStart: LDA SDMCTL STA DMACTL ; enable DMA LDA #0 STA CRITIC RTS ; -------------}----------------------------------------------------- psave: ldy ptr1 ; save system pointer sty svp1 ldy ptr1+1 sty svp1+1} rts prest: ldy svp1 ; restore system pointer sty ptr1 ldy svp1+1 sty ptr1+1 rts svp1: .word 0 ; ----------------------}-------------------------------------------- nread: .byte 0 nwrite: .byte 0 sample: .byte 2 ton: .byte 20 toff: .byte 20} tonmin: .byte 10 toffmax: .byte 30 qtime: .byte 100 totime: .byte 25 repeat: .byte 3 bytbuf: .byte 0 blen: .byte 0 rdb}uf: .blkb rdblen irgstat: .word 0 .globl _irginit .globl _irgread .globl _irgwrite bytbuf: .byte 0 blen: .byte 0 rdbYO_IRGINIT _IRGWRITE_IRGREADzENTERFUNEXITFUNLDAXYSP C E [ E \ E} ] E b E ^ E _ E ` E a9өө=өө Y Z e !="= \!}G"G \LD C E d E A Y Z eL  d0 Y } LLD C E AB  LLD , b <ȱ* c. c*ӊ \ !Ӯ ] !} ` ! < 6 LLDBLbL_B Lb , ` !,} a `,  !L  !, ^ L 8  !, `  _}0 L  L   L . c` c Z e Y Z`} e Zhh  6LbH [h` ԩB` /ԩB` W X` W X` d}}/* IRG Daemon to translate IR remote functions. Listens for * recognized packets, and sends out other packets. * * Copyri}ght 1994 David Deaven version 0.1 * Permission is granted to use, copy, and distribute this code, * provided that the use i}s non-commercial. * deaven@iastate.edu */ #include #include #include "irg.h" #ifdef M6502 #define voi}d int #else int start(FILE *f); int hextoc(char *s); int which(char *s, char c); void printp(char *s); int gettok(FILE *f, ch}ar *t); int iswhite(int c); void *pmalloc(size_t n); int getkey(); #endif /* These values work well with Mitsubishi, Sony, a}nd Sharp remotes. */ int sample = 2; /* timebase */ int ton = 20, toff = 20; /* pulse width -- sending */ int repeat = 3; } /* repeat send code */ int tonmin = 10, toffmax = 30; /* pulse width -- receiving */ int qtime = 100, totime = 25; /* quiet} time, timeout */ struct IRcode { char *name; /* user-defined string */ char *packet; /* IRG buffer */ void *map; /}* pointer to a mapped code */ void *next; /* next code in list */ }; struct Program { char act; /* action type */ vo}id *action; /* pointer to that action */ void *nxt; /* next action in program */ }; enum acts { NONE, CODE, EXEC }; str}uct IRcode *vocabulary = NULL; #define BUFLEN 16 char buffer[BUFLEN]; char *digit = "0123456789abcdef"; /* Search for a pa}cket in the known vocabulary. */ struct IRcode *identify(packet) char *packet; { struct IRcode *p; p = vocabulary; whi}le(strcmp(packet, p->packet))if((p = p->next) == NULL)return NULL; return p; } /* Search for a packet by name in the known} vocabulary. */ struct IRcode *nameid(name) char *name; { struct IRcode *p; p = vocabulary; while(strcmp(name, p->name}))if((p = p->next) == NULL)return NULL; return p; } /* Execute a program. */ void doProg(p) struct Program *p; { struct} IRcode *irc; printf("(execute: "); while(p != NULL) { switch(p->act) { case CODE: irc = p->action; printf(" }%s", irc->name); IRGwrite(irc->packet); break; case EXEC: printf("[no EXEC yet]\n"); break; default: break; } } p = p->nxt; } printf(")\n"); } void main() { int r; struct IRcode *irc; FILE *f; printf("IRG driver d}emo version 0.1\n"); printf("David Deaven c.1994 deaven@iastate.edu\n"); if((f = fopen("D:IRGDEMO.RC","r")) == NULL) } fprintf(stderr, "Cannot open init file\n"); else start(f); printf("starting IRG\n"); IRGinit(sample, ton, toff, repea}t, tonmin, toffmax, qtime, totime); while(1) { if((r = getkey()) > 0) { buffer[0] = 0xff; buffer[1] = r; } r = 2; } else r = IRGread(buffer, BUFLEN); if(r) { buffer[r] = '\0'; printp(buffer); printf("..."); } if((irc = identify(buffer)) == NULL) { printf("unknown packet\n(copied)\n"); IRGwrite(buffer); } else { } printf("%s\n", irc->name); if(irc->map)doProg(irc->map); } } } } /* Read definitions from file f */ in}t start(f) FILE *f; { struct IRcode *irc, *ircn, *v; struct Program *irl, *vl; char s[64]; int i, n; vocabulary=NUL}L; while(gettok(f, s)) { if(strcmp(s, "def") == 0) { if(gettok(f, s) == 0)goto eoff; if((irc = pmalloc(size}of(struct IRcode))) == NULL)return 3; irc->name = strdup(s); if(gettok(f, s) == 0)goto eoff; for(i=n=0; ipacket = strdup(s); irc->map = NULL; irc->next =  }NULL; printf("define %s = ", irc->name); printp(irc->packet); printf("\n"); if(vocabulary == NULL)voc }abulary = v = irc; else { v->next = irc; v = irc; } } else if(strcmp(s, "map") == 0) { if(gettok(f, s) } == 0)goto eoff; if((irc = nameid(s)) == NULL)goto unk; printf("map %s to (", irc->name); while(1) {  } if(gettok(f, s) == 0)goto eoff; if(strcmp(s, "end") == 0)break; if((ircn = nameid(s)) == NULL)goto unk; if}((irl = pmalloc(sizeof(struct Program))) == NULL)return 3; printf(" %s", ircn->name); irl->action = ircn; ir}l->act = CODE; irl->nxt = NULL; if(irc->map == NULL)irc->map = vl = irl; else { vl->nxt = irl; vl }= irl; } } printf(" )\n"); } else { printf("input error near: %s\n", s); return 1; } } } return 0; eoff: printf("unexpected end of file\n"); return 1; unk: printf("unknown tag %s\n", s); return 1; } }/* Convert two hex digits to a char. */ int hextoc(s) char *s; { int hi, lo; hi = which(digit, s[0]); lo = which(digit}, s[1]); return lo + (hi << 4); } /* Determine which character in s is c */ int which(s,c) char *s; char c; { int i; }for(i=0; s[i]!='\0'; ++i)if(s[i] == c)return i; return -1; } /* Print a string in hexadecimal */ void printp(s) char *s; }{ while(s[0]!='\0') { fputc(digit[s[0]>>4 & 0xf], stdout); fputc(digit[s[0] & 0xf], stdout); ++s; } } /* Rea}d one token from f */ int gettok(f, t) FILE *f; char *t; { int i, n; do { i = fgetc(f); if(i == EOF)return 0; }} while(iswhite(i)); t[n = 0] = i; do { i=fgetc(f); if(i == EOF)return 0; t[++n] = i; } while(!iswhite(i)}); t[n] = '\0'; return 1; } /* White space on the Atari */ int iswhite(c) int c; { if(c==' ' || c=='\t' || c==155 ||} c=='\n')return 1; return 0; } int getkey() { #ifdef M6502 int r; char *ch; ch = 0x2fc; if((r = (*ch)) != 0xff) { } (*ch) = 0xff; return r; } #endif return -1; } 502 int r; char *ch; ch = 0x2fc; if((r = (*ch)) != 0xff) { : ?Lf%HehL!`ܠؠԠРH8咅h`H8h`֠ҠΠʠƠ±}HȱhL!``e` L L!L!L!L!L!L! ȘL! L! M Hȑh`HȱhL }HȱhL Hȱh ` ` .!HȥhL! .!L! `HȑhL!L!HH hhL!HH }hhL! H*h`L!`L!`HIhIi```IHIh`e` !L `}` !L! !L! !L! ! !L ! !L  &L!L! 󨥂fjL! eHehL!  }8H哪hL! HhL! EHEhL! %H%hL!`\_ łXTM łFBE 0>7ł86/ 䃐-&ł!}'% 0ł 䃐 ł`` 0ł 䃐ł۰ 0łʰ 䃐ł𹰼 "}L H hL lHh` !L !L hh捠ilŕŔ #}liL#`L!  ! Ɣ !$ \$& $ \$& 򦓥 !`H$}eeh`` ! ! ! !Ńł &&L$FfFf3ō%}Ō8包卅FfFfͥ !ĕ !` t$L! ` &}`S L L L i?H ihL%  4l  dI''} k# M %% B! u  u  !  9( u  ! B! "  Lq#L% u  Lq# k# M %% B! u  u(} !  9( u  ! B! "  Lq#LG& u  Lq# k# M Z'  [5 u "L7' u !L' u  !)} B!e'  u !  [5 u  !  2L%'i'  [5L%'L%'L%' #&'L' u  ! B!L&x'  [5  Lq#0123*}456789abcdef(execute: %s[no EXEC yet]) k# i S)  [5p)  [5) )  q: B! ":: )+}  5L' u  ))  [5%% %% %% %% %% %% %% %%  1 1 B! ,} #3Ģ% i!Ģ%  Y"  u i! B!L(Ģ%   j2 B! u !LJ)Ģ%  u Y" i!-}%  T/̢)  [5Ģ%  % B! "Т)  [5Ģ%  2LJ))  u !  [5 u  ! ! u  .}!  &L;( + Lq#IRG driver demo version 0.1David Deaven c.1994 deaven@iastate.eduD:IRGDEMO.RCrCannot open init file/}starting IRG...unknown packet(copied)%s k#N 7 %%P u   \0L. /  9 "L-0},P u   \0 "N  L*.  >:L B! " N  Lq#L u   ; R!P u  1} \0 "N  L*. B! B! u   M% "YL+ u  Y" B!L*  u #  B! $ Y"  2}  u Y"  o. i!L*  u #  B! $ Y" i!L u   ; !L u  !L u  3}!/ N u !  [5L u  !  T/0  [5%% "L u H B!%%L*,H u N u  !L u H B!L.4} 0  9 "L-P u   \0 "N  L*.  6&L B! "N  LJ.0 N u 5}!  [5P u   \0 "N  L*. 0  9 "L-  6&J B! "N  LJ.6}  >:F B! " N  Lq#0 L u !  [5F u L u  !F u  i!F u  !L u  ! 7} "L u H u F B! !L-D u H u  !F u D B!L,0  [5L.0   [5N  Lq#L)N 8} Lq#L/.N 7 40  [5N  Lq#LO.N 7 L0   [5N  Lq# k# a %%  u !  . B!%%  u9}  Y" !  . B! u  u  " Y" # Lq# k# M B! u  u Y" ! "AL/ u B!L.:} u  u Y" !  " u  Lq#L /  Lq# k# u ! "L/%%  u !  8"  " Y" ! ;} ::  a;%%  u !  " Y" ! ::  a; u  B!LW/Lq#defdefine %s = mapmap %s to (end <}%s )input error near: %sunexpected end of fileunknown tag %s k# a  u  ; B! u " # Lq# u =}  I1Lb0 u  B! Y"  u i! u  ; B! u " # Lq# u  u  B! Y"  u i!>} u  I1 !L0 u  u Y" i! # Lq# k# u "3 u  "" u " u "?}Lq#Lq# k# a  B! u ! B! " u i! u # Lq# # Lq# k# u K4 u L4 u M4@} u R4 u N4 u O4 u P4 u Q49өө=өөI4J4U443- \37 \Lq# k# u T4 u 14I4JA}4U4L2T40I44 <4Lq# k# u 14B  <4Lq# 4R4,3ȱ*S4.S4*ӊL4 4ӮM4 B}4ݢѮP4 4,3п &4 <4Lq#BLbL_B Lb 4ЮP4 4,Q4P4, 4L 4 4,C}N44L 48 3 4,P4 O40 3Ly3 3L3 34L 4.S4`S4J4U4I4J4`D}U4J4hh4 &4LbHK4h`ԩB`/ԩB`G4H4`G4H4` dE} k# !44  #> 44 F}  {'Lq# k# a    }! Y" ! }! Y"  }! h" B! u # u  B!  5 # Lq# k# M ::   G} }! Y" ! }! Y"  }! h"  5  Lq# k## 7  B!% u # % B! $ ! B! u ! !L9 u #% "3 uH} #  B! $ #) ! a; u  B!L5L/6 u  B! u #% "0 u #  B! $ #) ! a; u  B!L5I} u #- " B! u  B!L6 B! u #0 " 0 B!L6  B! u # >B u #  B! $ J}  < B! u # > u  B!L6L#7 B! u #. "< u  B!  < B! u # > u  B!K}LN7Ly7 B!% u # % B! $ !! B!  B! u #  B! $ # >Lu8 # u i!  Y" i!L8! u L} B!L8! !  =L8! !   : B! ! ! -% ! u Y" i! u # Lq# Y# a  u # 3? u  B!L< B! u !Le<U} B! u  B!Lr< #L<-U<+ B! u # >=  u $  u #  B! $ ! Y" 0 h" B!L{< V}! u $ # Lq# a# a  u  B! ! 8" B! ! " B! ! 8"  " B! ! ! u #%  " W} u Y" i! u # " u #0 Y" i!L= u #7 Y" i! u  B! ! u t$ B! !L< ! i! X}! > # Lq#? Ԇ !Ԇթ- ؠ0L=)ȑ` 0:`` NY}HɛD >ȥi揠 >Hhɛ`!8`` A[i ` Y# a  ! ! M%Z} Y"  h" B! ! u "O u ! B! u #  B! $  u ! i! u #  B! $  u i!L> # Lq# Y# [}! ": ! "" ! " ! 3#Lq# i! u #  B! $  u i!L> # Lq# Y# Mdef vcr_chup ab6edf def vcr_chdn ab6eef def vcr_volup abddee def vcr_voldn abddb7 def vcr_play ab6f7e def vcr_rew ab6f5b80 de!]}f vcr_ff ab6f77 def vcr_pause ab6f5780 def vcr_rec ab6f5f def vcr_jogfwd ab6f6ac0 def vcr_jogrev ab6d7560 def vcr_jogon ab6eb!^}6c0 def vcr_jogoff ab6eab60 def vcr_qv ab6dbb80 def vcr_cancel ab6d6f80 def vcr_enter ab6db5c0 def vcr_inpsel ab6ed5c0 def vc!_}r_index+ ab6eaf80 def vcr_index- ab6eb780 def vcr_power ab6efe def vcr_dos ab6d5dc0 def vcr_n0 ab6ddf def vcr_n1 ab6ffc def v!`}cr_n2 ab6fbe def vcr_n3 ab6fde def vcr_n4 ab6faf def vcr_n5 ab6fee def vcr_n6 ab6fb7 def vcr_n7 ab6fd7 def vcr_n8 ab6fab80 de!a}f vcr_n9 ab6dfe def key_space ff21 map vcr_qv vcr_dos end map key_space vcr_n0 vcr_n1 end r_n7 ab6fd7 def vcr_n8 ab6fab80 de [1 REM IRGSCAN.BAS (c) 1993 D. Deaven 2 REM Sample IRG driver 90 BUFLEN=40:SAMPLE=23:QTIME=100:TOTIME=255:REPEAT=3 100 GOSUB 1%c}0000:T=(64+5*SAMPLE)/1.78979:T=INT(T*10)/10 110 GRAPHICS 8:DL=PEEK(560)+256*PEEK(561):SMEM=PEEK(DL+4)+256*PEEK(DL+5) 111 BUF=%d}SMEM+2000 120 ? "T=";T;"usec [S]END OR [R]ECEIVE" 130 OPEN #1,4,0,"K:":GET #1,C:CLOSE #1 140 IF C=ASC("S") THEN FOR I=1 TO RE%e}PEAT:A=USR(1536,BUF,BUFLEN,SAMPLE):NEXT I 150 IF C<>ASC("R") THEN 130 160 A=USR(1536,BUF,BUFLEN,SAMPLE,QTIME+256*TOTIME) 170 %f}IF A<>0 THEN ? "TIMEOUT":GOTO 120 180 GOTO 130 10000 RESTORE 10001:FOR I=0 TO 223:READ J:POKE 1536+I,J:NEXT I:RETURN 10001 D%g}ATA 169,0,120,141,14,212,141,0,212,133,213,169,57,141,2,211,169 10002 DATA 1,141,0,211,169,61,141,2,211,104,168,192,3,48,30,1%q}B%DOS SYSB*)DUP SYSBMSHARDWAREPS BIRG H B?IRG M65B IRG OBJB-IRGDEMO C BAIRGDEMO COMB\IRGDEMO RC B bIRGSCAN BASBxIRGSCAN M65B#PULSES PS BrREADME B README HAR04,133,204 10003 DATA 104,133,203,136,104,104,133,205,136,104,104,133,207,136,240 10004 DATA 119,104,141,223,6,104,141,222,6,%r}136,240,10,152,240,90,104,104 10005 DATA 136,208,251,240,83,160,0,169,1,32,212,6,44,16,208,240,244,200 10006 DATA 204,222,6,2%s}08,242,172,223,6,174,222,6,44,16,208,240,14,32,212 10007 DATA 6,202,208,245,136,208,239,160,1,76,155,6,160,0,162,8,173,16,208%t} 10008 DATA 106,38,206,32,212,6,202,208,17,165,206,73,255,145,203,162,8,200 10009 DATA 196,205,208,231,160,0,240,7,32,209,6,2%u}34,76,119,6,132,212,173 10010 DATA 47,2,141,0,212,169,64,141,14,212,88,96,160,255,162,8,200,177 10011 DATA 203,133,206,38,206%v},169,0,42,141,0,211,32,212,6,202,208,10,162 10012 DATA 8,196,205,208,231,160,0,240,208,32,209,6,76,179,6,234,234,96,72 10013 %w}DATA 138,166,207,202,208,253,170,104,96,0,0 10012 DATA 8,196,205,208,231,160,0,240,208,32,209,6,76,179,6,234,234,96,72 10013 $,; --------------------------- ; Infrared gateway code (IRG) ; Simple version to be used ; with IRGSCAN.BAS ; (c) 1993 David D)y}eaven ; --------------------------- include bufadd = 203 ; and 204 bufsiz = 205 bytbuf = 206 sample = 207 org)z} $600 PROC ; BASIC "USR" entry USR LDA #0 SEI ; stop IRQ... STA NMIEN ; ...and NMI STA DMACTL ; prevent DMA STA FR0+1 ){}; zero return LDA #%0011_1001 ; set up PIA STA PACTL ; bit A0 output LDA #%0000_0001 STA PORTA LDA #%0011_1101 STA PAC)|}TL PLA ; get # args TAY CPY #3 ; need 4 args BMI :badarg PLA STA bufadd+1 PLA STA bufadd DEY PLA PLA STA bu)}}fsiz DEY PLA PLA STA sample DEY BEQ Send ; 3 arg --> SEND PLA STA totime PLA STA qtime DEY BEQ Receive ; 4 arg )~}--> RECEIVE :badarg TYA ; pop all args BEQ Exit ; and return :nexta PLA PLA DEY BNE :nexta BEQ Exit EPROC PROC ; ;)} Fill the buffer with data. ; Receive LDY #0 ; detect gap LDA #1 ; IR is LSB :wait JSR Delay BIT TRIG0 BEQ Receive INY )} CPY qtime BNE :wait LDY totime :mark0 LDX qtime :mark BIT TRIG0 BEQ :start JSR Delay ; wait -- first pulse DEX BNE :m)}ark DEY BNE :mark0 LDY #1 JMP Exit ; timeout :start LDY #0 LDX #8 :loop LDA TRIG0 ; 4 ROR A ; 2 ROL bytbuf ; 5 JSR )}Delay ; 6 + delay DEX ; 2 BNE :no ; 3 LDA bytbuf ; 3 EOR #$FF ; 2 STA (bufadd),Y ; 6 LDX #8 ; 2 INY ; 2 CPY bufsi)}z ; 4 BNE :loop ; 3 LDY #0 BEQ Exit :no JSR adjust ; 6+10 cycles NOP ; 2 JMP :loop ; 3 EPROC ; ; Exit -- restart DMA,)} interrupts ; Exit STY FR0 ; return code LDA SDMCTL ; enable DMA STA DMACTL LDA #$40 ; enable NMI STA NMIEN CLI ; enab)}le IRQ RTS ; ; Send the buffer out ; PROC Send LDY #$FF LDX #8 :loop INY ; 2 cycles LDA (bufadd),Y ; 5 STA bytbuf ; 3 )}:sloop ROL bytbuf ; 6 LDA #0 ; 2 ROL A ; 2 STA PORTA ; 4 JSR Delay ; 6 + delay DEX ; 2 BNE :no ; 3 LDX #8 ; 2 CP)}Y bufsiz ; 4 BNE :loop ; 3 LDY #0 BEQ Exit :no JSR adjust ; 6+10 cycles JMP :sloop ; 3 EPROC ; waste 10 cycles adjust N)}OP ; 2 cycles NOP ; 2 cycles RTS ; 6 PROC ; ; Wait a delay time, preserve A, X, Y ; time = (20+5*sample) clock period)}s ; Delay PHA ; 3 cycles TXA ; 2 LDX sample ; 3 :loop DEX ; 2 BNE :loop ; 3 TAX ; 2 PLA ; 4 RTS ; 6 EPROC qtim)}e DB 0 totime DB 0 assert * < $700 END ample ; 3 :loop DEX ; 2 BNE :loop ; 3 TAX ; 2 PLA ; 4 RTS ; 6 EPROC qtim(+%! %%Title: /tmp/xfig-export010130 %%Creator: fig2dev %%CreationDate: Wed Aug 11 08:50:28 1993 %%For: deaven@hubbell (David D-}eaven) %%Pages: 1 %%BoundingBox: 195 225 417 567 %%EndComments /$F2psDict 32 dict def $F2psDict begin $F2psDict /mtrx matri-}x put /DrawEllipse { /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /-}savematrix mtrx currentmatrix def x y translate xrad yrad scale 0 0 1 startangle endangle arc savematrix setmatrix } def n-}ewpath 0 0 0 0 0 1 DrawEllipse stroke end /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psE-}nteredState restore end} def %%EndProlog $F2psBegin 1 setlinecap 1 setlinejoin 0.000000 571.000000 translate 0.900 -0.900 s-}cale 612 0 translate 90 rotate 1.000 setlinewidth [4.000000] 0 setdash % Ellipse newpath 259 69 60 60 0 360 DrawEllipse stro-}ke [] 0 setdash [4.000000] 0 setdash % Ellipse newpath 309 189 14 14 0 360 DrawEllipse stroke [] 0 setdash % Polyline newp-}ath 224 114 moveto 224 44 lineto 229 44 lineto 229 119 lineto stroke % Polyline newpath 234 119 moveto 234 44 lineto 239 44 -}lineto 239 124 lineto stroke % Polyline newpath 244 124 moveto 244 44 lineto 249 44 lineto 249 124 lineto stroke % Polyline-} newpath 254 129 moveto 254 44 lineto 259 44 lineto 259 129 lineto stroke % Polyline newpath 264 129 moveto 264 44 lineto 26-}9 44 lineto 269 129 lineto stroke % Polyline newpath 274 124 moveto 274 44 lineto 279 44 lineto 279 124 lineto stroke % Pol-}yline newpath 284 119 moveto 284 44 lineto 289 44 lineto 289 119 lineto stroke % Polyline newpath 294 119 moveto 294 44 line-}to 299 44 lineto 299 114 lineto stroke % Polyline newpath 304 104 moveto 304 44 lineto 309 44 lineto 309 99 lineto stroke %-} Polyline newpath 314 89 moveto 314 49 lineto stroke [1 3.000000] 0 setdash % Polyline newpath 324 189 moveto 319 64 lineto-} stroke [] 0 setdash [1 3.000000] 0 setdash % Polyline newpath 214 109 moveto 299 199 lineto stroke [] 0 setdash [1 3.0-}00000] 0 setdash % Polyline newpath 64 159 moveto 64 184 lineto stroke [] 0 setdash [1 3.000000] 0 setdash % Polyline newp-}ath 84 159 moveto 84 184 lineto stroke [] 0 setdash % Polyline newpath 4 204 moveto 24 204 lineto 24 184 lineto 44 184 line-}to 44 204 lineto 64 204 lineto 64 184 lineto 84 184 lineto 84 204 lineto 144 204 lineto 144 184 lineto 164 184 lineto 164 204-} lineto 184 204 lineto 184 184 lineto 204 184 lineto 204 204 lineto 224 204 lineto 224 184 lineto 244 184 lineto 244 204 line-}to 304 204 lineto 304 184 lineto 324 184 lineto 324 204 lineto 344 204 lineto 344 184 lineto 364 184 lineto 364 204 lineto 38-}4 204 lineto stroke % Polyline newpath 119 224 moveto 114 204 lineto stroke newpath 114.000 212.246 moveto 114.000 204.000 -}lineto 117.881 211.276 lineto stroke % Polyline newpath 44 164 moveto 64 164 lineto stroke newpath 56.000 162.000 moveto 64.-}000 164.000 lineto 56.000 166.000 lineto stroke % Polyline newpath 104 164 moveto 84 164 lineto stroke newpath 92.000 166.00-}0 moveto 84.000 164.000 lineto 92.000 162.000 lineto stroke % Polyline newpath 29 224 moveto 34 204 lineto stroke newpath 30-}.119 211.276 moveto 34.000 204.000 lineto 34.000 212.246 lineto stroke /Times-Roman findfont 12.000 scalefont setfont 244 29 -}moveto 1 -1 scale (40kHz) gsave 0.000 rotate show grestore 1 -1 scale /Times-Roman findfont 12.000 scalefont setfont 54 154-} moveto 1 -1 scale (500 usec) gsave 0.000 rotate show grestore 1 -1 scale /Times-Roman findfont 12.000 scalefont setfont 14-} 244 moveto 1 -1 scale ("1" bit) gsave 0.000 rotate show grestore 1 -1 scale /Times-Roman findfont 12.000 scalefont setfont-} 104 244 moveto 1 -1 scale ("0" bit) gsave 0.000 rotate show grestore 1 -1 scale /Times-Roman findfont 12.000 scalefont set-}font 83 256 moveto 1 -1 scale (\(missing pulse\)) gsave 0.000 rotate show grestore 1 -1 scale /Times-Roman findfont 18.000 -}scalefont setfont 41 72 moveto 1 -1 scale ("110111011") gsave 0.000 rotate show grestore 1 -1 scale % Polyline newpath 234 -}224 moveto 314 224 lineto stroke newpath 306.000 222.000 moveto 314.000 224.000 lineto 306.000 226.000 lineto stroke /Times--}Roman findfont 12.000 scalefont setfont 264 239 moveto 1 -1 scale (time) gsave 0.000 rotate show grestore 1 -1 scale showpa-}ge $F2psEnd nt 12.000 scalefont setfont 264 239 moveto 1 -1 scale (time) gsave 0.000 rotate show grestore 1 -1 scale showpa, This write-up describes how to use the software provided in this release (version 0.1) of the IRG (Infrared Gateway) for the 1}Atari 8-bit computers. Most of this was originally submitted to the _Atari_Classics_ magazine as an article, but has not bee1}n published. Enjoy! David Deaven -- deaven@iastate.edu ---- Files included in this distribution ------------------------ 1} README, README.HARDWARE -- instructions hardware.ps, pulses.ps -- PostScript pictures to go with the instructions. 1} irgscan.bas -- listed Atari BASIC program (ASCII, not binary) irgscan.m65 -- Assembler program source for the code that is1} used in irgscan.bas irg.h irg.m65 irg.obj -- IRG driver software for CC65 irgdemo.c irgdemo.com -- CC65 example of 1}using the IRG driver irgdemo.rc -- init file read by irgdemo.com (see section IV). ---------------------------------------1}-------------------------- 0. Installation and running the programs a) Build the IRG circuit and plug it into your Atari1}, in joystick port 1. See README.HARDWARE for instructions. b) Copy IRGSCAN.BAS, IRGDEMO.COM, and IRGDEMO.RC onto 1}a disk, place it in the default drive ("D:"), usually drive 1, and run IRGDEMO.COM. It will load definitions fro1}m IRGDEMO.RC and begin reporting any IR control codes received on the IRG. You might want to write down the code1}s for your particular remotes, to include in the initialization file. c) If no codes are received by IRGDEMO.COM, c1}hances are your remote uses a different standard than Mitsubishi, Sony, and Sharp remotes do. In this case, run 1}IRGSCAN.BAS (requires the BASIC cartridge) and try scanning some codes in to verify that the IRG is working. You1} can adjust the parameters in IRGDEMO.C once you determine what the form of your remote's signal is. -----------------1}------------------------------------------------ The Infrared gateway (IRG) for the Atari 8-bit computers. David Deaven -- de1}aven@iastate.edu Have you ever wondered how TV and VCR remote controls work? Have you ever dreamed of accessing your At1}ari Classic by remote control? If so this project will be right up your alley -- I'll show you how about ten dollars worth of1} electronic parts from your local Radio Shack can enable your Atari to receive infrared (IR) signals from most TV, VCR, and s1}tereo remotes, and send IR signals to most any IR remote-controlled appliance. The parts fit in a small box I call an IRG (I1}nfraRed Gateway) which connects to a joystick port on your Atari 400/800/1200/XL/XE. The file README.HARDWARE describes1} how to build the IRG, and this file describes how to control it with some simple machine language subroutines called from B1}ASIC or CC65. I. IR protocols First let's briefly consider how an IR remote works. In the nose of each of your remotes1}, there's a bank of infrared LEDs that transmit either IR modulated at 40kHz, or nothing, these two possibilities representin1}g logic level 1 or 0. Your TV or VCR listens for a 40kHz IR signal and demodulates it into a serial pulse stream. (This is i1}llustrated in the attached PostScript figure "pulses.ps".) When the proper stream is sent, the TV or VCR executes a remote fu1}nction. The key point is that the 40kHz IR signal is either present (logic level 1) or not (logic level 0), so the IR 1}link is like a single (one-way) TTL data line. The protocol each manufacturer uses to send information is up to them, but the1}re are some common standards. Most IR remotes transmit packets of roughly 30 bits using a form of pulse-code modulation (PCM)1}. Within one packet information specifying manufacturer and appliance type is usually given, so that different manufacturer's1} remotes don't interfere with one another. Some remotes send several different packets even when only one button is being pus1}hed in order to distinguish between a button being held down and one that is being pressed repeatedly. Usually a single packe1}t is enough to execute a function, but at least one of my appliances will only respond to a correct sequence of multiple pack1}ets. II. Some simple software Once you've got the IRG hooked up, you are ready to play with it. To do that, you'll nee1}d a bit of machine code to send and receive IR signals. The program IRGSCAN.BAS listed with this file is a self-contained exa1}mple program which contains a short machine language routine that simply digitizes input from the IRG at precisely timed inte1}rvals adjustable from 64 to 1339 clock cycles (36 to 748 microseconds). The assembly code contained in IRGSCAN.BAS is also pr1}ovided (IRGSCAN.M65) so you can get some idea of how it works. Once the IR data is digitized IRGSCAN.BAS can also send it bac1}k out over the IRG. Let's take a closer look at how the machine code IRGSCAN.M65 works. One problem I had to solve was 1}that the pulse width of 500 microseconds used in the IR standard corresponds to only 895 microprocessor cycles. A packet 30 1}bits long, or 60 pulse widths long, lasts about 1/30 sec, during which time the Atari's 6502 would normally process two verti1}cal blank interrupts, and two screenfuls of DMA cycles would also be stolen from the 6502 by ANTIC. This introduces signific1}ant uncertainties into the timing loops I wanted to use in my code, so my solution was to simply turn off DMA and IRQ/NMI int1}errupts, avoiding vertical blanks, keyboard interrupts, and ANTIC cycle-stealing entirely at the cost of losing the display d1}uring IR transmission and reception. I experimented with other approaches based on keeping track of interrupt service routine1} delays, for example by reading ANTIC's vertical line counter (VCOUNT), but I had little success. The DMA cycles stolen by A1}NTIC are highly dependent on the display mode, and I wanted this code to work with any display. In my applications, the Atar1}i running the IRG isn't even hooked up to a monitor, so this is no big deal. (Even with a display, you still have a usable p1}icture, since the screen is stable as long as there are no IR transmissions going on.) IRGSCAN.M65 gets loaded into mem1}ory at page six. When this routine is called from BASIC with 4 arguments, it scans the IRG and stores bits collected at preci1}se time intervals into a buffer region. You can set the sampling time interval by changing the variable SAMPLE in IRGSCAN.BAS1}, which is a single byte. Values of 0 through 255 produce digitization time intervals of 64+5*SAMPLE clock cycles. When calle1}d with 3 arguments the routine sends the buffer out over the IRG. Each of the eight bits in the buffer bytes are used, in ord1}er from MSB to LSB. This allows ANTIC to display the buffer directly on the screen in a two color graphics mode, assuming scr1}een memory is used for the buffer area. IRGSCAN.BAS does this with the high-resolution graphics mode's (BASIC mode 8) display1} memory for the buffer. You can scan a remote using IRGSCAN.BAS to see what kind of signals it generates, and play back the s1}equence to mimic the effects of the remote control. Try changing the timing parameter SAMPLE to see a higher or lower resolut1}ion version of the IR signal. At this point, you can adjust the center frequency of the 555 timer in your IRG to precis1}ely 40kHz, if you haven't already done so. Just scan, say, a TV function like "mute" into memory using IRGSCAN.BAS, then poin1}t the IRG at the TV, and play the signal repeatedly. Adjust the trimmer until the TV responds. (The "mute" function is conven1}ient since you won't have to look at the TV to see when it's responding.) My IRG had quite a broad range of acceptable trimme1}r settings -- it doesn't have to be perfect. With some more programming effort, IRGSCAN.BAS could be modified so as to 1}serve as a "universal remote," with a library of digitized functions. Unfortunately, IRGSCAN.BAS provides no easy way to *rec1}ognize* incoming bit patterns. That problem can be solved with just a little bit more effort. III. The IRG driver software 1} Let's look at a schematic for a more sophisticated receiving algorithm. The IRG driver, which is provided here in vers1}ions suitable for both BASIC and CC65, installs a vertical blank interrupt (VBI) routine that constantly (well, every 1/60 s1}econd) checks for IRG activity. When IR input is detected, the driver takes over and scans the IRG, decoding the IR bit patt1}ern on the fly. This allows a BASIC or C program to recognize a particular IR signal, and it solves another problem with digi1}tizing: excessive memory usage. You can see from running IRGSCAN.BAS that an IR packet contains only a few bytes of data, yet1} IRGSCAN.BAS uses a hundred bytes or so of storage to keep it in digitized form. The IRG driver works with IR signal codes in1} a packed form, requiring only a few bytes per packet. The driver uses a few parameters to describe how the incoming si1}gnal should be digitized. These are set by calling the initialization routine: void IRGinit(int sample, int ton, int toff1}, int repeat, int tonmin, int toffmax, int qtime, int totime) Here "sample" controls the sampling rate, or timebase of 1}the digitizer and sending code, using the same delay subroutine IRGSCAN.BAS uses. "ton" ("toff") is the on (off) time for an 1}ideal "1" ("0") pulse. "repeat" is the number of times to repeat the send operation of a single code. Most equipment works b1}etter when the control codes are repeated several times. "tonmin" is the minimum values for valid "1" pulses. "toffmax" is th1}e maximum off time for a "0" pulse -- longer than this means end of packet. "qtime" is the required "quiet time" of IRG inac1}tivity before starting to receive a packet. "totime" is the timeout time -- the driver times out if spurious pulses are foll1}owed by inactivity of this duration. Good values for these parameters are sample = 2, ton = 20, toff = 20, repeat = 3, 1}tonmin = 10, toffmax = 30, qtime = 100, totime = 25. Once installed, the driver can send and receive packets via the ro1}utines int IRGread(char *buffer, int size) = # bytes returned int IRGwrite(char *buffer) = 0, or 1 if IRG is active whe1}re "size" is the maximum buffer size, and all strings are null terminated. The receive code has a built-in buffer, so it won2}'t drop packets if you don't read them right away. (The size of this buffer is set inside the driver source code, so you can2} change it there.) You can look at the driver code ("irg.m65") to see more of the implementation details. IV. Demo program 2} I have provided a simple example program "irgdemo.c" which can be used as a translator between different sets of IR code2}s. For example, it can read remote codes from your VCR remote and map those functions onto your TV by transmitting new codes2} to the TV when the proper VCR codes are received. The demo program reads an init file containing two types of information. 2} First, lines like def vcr_chup ab6edf means that the IR code "ab6edf" corresponds to the named tag "vcr_chup" (VCR chann2}el up). After all of the IR packets are defined in this manner, lines like map vcr_volup tv_volup end specify that if t2}he IRG detects the "vcr_volup" packet, it should send the "tv_volup" packet. More than one packet may be output by the IRG, 2}for example map vcr_qv vcr_n2 vcr_n1 vcr_enter end maps the "vcr_qv" packet (this is an unused button on my remote) into 2 }the three-packet sequence that changes the channel to channel 21. One last feature is that while the demo program is ru2 }nning, if a keyboard key is pressed it will simulate reception of the packet ffXX where XX = the internal Atari code for that2 } key. So def key_space ff21 defines the "packet" corresponding to pressing the space key. Included with this release is 2 }a sample irgdemo.rc file that contains some definitions for a Mitsubishi VCR. V. Applications and ideas I originally b2 }uilt my gateway in order to understand how IR remotes operate, and because I was interested in controlling home appliances an2}d security systems by IR remote. The Atari was a perfect match because it's so easy to connect to the outside world. But, th2}e applications go further than this. I use my IRG as a "universal" remote interface to my TV, VCRs, and cable box. My Hi-fi 2}VCR has a complicated remote control with many more functions on it than I use, such as control over a TV I don't own. An Ata2}ri/IRG translates the codes from my VCR remote to control my TV, backup VCR and cable descrambler. Now I have one remote, wit2}hout losing the VCR's special features such as jog/shuttle control. The universal remotes sold commercially don't have the m2}echanical hardware required to emulate these functions. Other applications of an Atari/IRG also spring to mind: 1) You2}r VCR could be programmed to record at a given time by an Atari/IRG which deciphers those VCR+ numbers found in the TV guides2}. Especially since the VCR+ algorithm has been programmed on the Atari. I am currently working on adding VCR+ capability to t2}he IRG code. 2) Your VCR can be programmed to record a scrambled cable channel, the Atari/IRG handles switching the cable bo2}x to the correct channel at the correct time, and starting/stopping the VCR. 3) The Atari/IRG could be interfaced to an audi2}o/video switch box that controls what input your TV gets. Besides having TV tuner, VCR 1, VCR 2, Atari 2600, Atari 7800, NES2}, etc., choices, one screen could be the Atari/IRG display, with visible menu selections (all accessed via IR remote) for tim2}e-programmed functions. 4) An Atari/IRG programmed to act as a "recording studio" controls a CD player, stereo, and Hi-fi VC2}R and allows you to select a list of songs to put on one tape. (Thanks to Chris Chiesa for suggesting this one.) 5) An Atari2}/IRG with computer-readable TV program information downloaded into it from a subscription computer service like Prodigy or Co2}mpuserve could directly select TV programs, performing your local cable channel conversion invisibly. I hope you enjoy 2}building and using the IRG. Please drop me a line (preferably by e-mail) if you find any unusual applications of the IRG. I'2}m always interested in what people are doing with the Atari 8-bit machines! David Deaven deaven@iastate.edu s of the IRG. I'0mHow to build the IRG (Infrared Gateway) hardware for the Atari 8-bit David Deaven -- deaven@iastate.edu -- April 1994 T6!}his write-up describes how to build the IRG circuit and attach it to your Atari 8-bit computer on a joystick port. The IRG c6"}ould also be used with other computers providing one TTL input and one TTL output. (The joystick ports on the Atari are just6#} PIA lines.) Detecting the 40kHz IR carrier turns out to be an easy task. Radio Shack has started carrying the Sharp GP6$}1U52X IR receiver hybrid circuit for the relatively low price of $3.49 (about the same as mail order prices). This remarkable6%} little metal box has only 3 pins: power (+5VDC), ground, and TTL out; it does all of the 40kHz bandpassing and demodulation 6&}for you. Its output is low (0 volts) when 40kHz IR is detected, and high (5 volts) otherwise. With no other parts, the GP1U56'}2X can be connected directly to the Atari joystick port, which provides 5VDC. The IRG sends signals with the simple cir6(}cuit shown in the accompanying PostScript figure (hardware.ps). This circuit is a standard oscillator based on the 555 time6)}r chip and a few other parts. The small variable resistor (trimmer) is used to adjust the output frequency to precisely 40kH6*}z. The 555 reset pin disables oscillation when held low, so it can be connected directly to a PIA output line. (On the Atari6+}, the PIA lines are all configured as inputs on power-up. Don't worry about plugging the IRG into your Atari even if you don6,}'t have the IRG software driver running. It won't harm anything to have the IRG input line connected to a PIA line configure6-}d as an input.) I used a small plastic case and mounted the 555 and related components on a small piece of perfboard cu6.}t to fit inside. You can use any style of circuit construction you are comfortable with. I soldered small pieces of 22 gauge6/} stranded wire to make the 555 circuit connections and to hook up the GP1U52X, which fits into a corner of the case near a ho60}le drilled to make a window for the IR detector. I mounted one IR LED in another hole drilled into the case. A small dab of s61}uper glue holds these nicely. Be sure that you connect the ground pin and metal case of the GP1U52X together, providing a shi62}eld against external electromagnetic signals, and isolating the sensitive detector from the milliwatt 40kHz oscillator you ar63}e installing in the same case! To connect the IRG to your Atari, I suggest using a cable from a broken joystick, provided you64} have one which has a +5VDC wire (the stock Atari joysticks do not). Refer to figure 2 for the joystick pinout. Use a gromme65}t or some epoxy to secure the cable in place where it enters the box. If you don't have an old cable, Radio Shack also sells 66}DB9 connectors that fit into the Atari joystick ports and you can make your own cable. However, the ports work best with slim67}mer DB9 connectors. All of the parts required to build the IRG are available at Radio Shack, and I've listed some part number68}s for you on the schematic. I also put a mini phone jack carrying the 555 output on the rear face of my IRG, which allo69}ws me to add extra IR LEDS with a two-conductor cable. This is useful if not all of the appliances to be controlled are in o6:}ne place, or even in one room. With a 150 ohm resistor the IR LED current is about 15ma, and the 555 can drive up to 200ma or6;} so, allowing you to connect up to 10 IR LEDS in parallel to the IRG (remember to include a 150 ohm current-limiting resistor6<} in series with each LED!). If you have an oscilloscope, then once the IRG is wired up you can adjust the trimmer so th6=}at the 555 is generating 40 kHz output. If you don't have access to a scope, relax. Once you get the software going, you can 6>}adjust the trimmer using a remote-controlled appliance like a TV or VCR-- see the README file. the software going, you can 4a