'>Hxtr3-7.BSx '============================================================== 'Milford Instruments http://www.milinst.com 'Hextor Design, Bug Commander - Behavioural Operating System 'and the Behavioural Controller programs by David Buckley '================================================================ '{$stamp BS2Sx} DEBUG "prog7" '============================================================== 'Hxtr3-0.BSx - Main 'Hxtr3-1.BSx - Activity sequencer 'Hxtr3-2.BSx - US Behaviour 'Hxtr3-3.BSx - Direct Control 'Hxtr3-4.BSx - Prog4 'Hxtr3-5.BSx - Prog5 'Hxtr3-6.BSx - LCD menu 'Hxtr3-7.BSx - Utils- LCD control and IR remote 'Hxtr3-Doc.BSx - Meta Commands and Program Headers '============================================================== 'Bugs '---- 'Cmndlearner only remembers 7 slots, ' no indication that all slots used, ' needs to check not overwriting pgm, ' indexing is hard to understand '============================================================== 'History '------- '16-7-11 IR page3 IR1 = Do Default added '16-8-05 Cmndlearner added ' note there are only about 256 bytes of storage available, ' ie ~ 8*32 moves, actually coded 6 slots ' added to tellBOSc to remember cmnds ' if Flearn=0 then _tell ' write (tmpmem+lcmnds),BOScmnd ' lcmnds =lcmnds +1 ' write (tmpmem+lcmnds),"z" '15-8-05 LCDkeys - ">"+"do" => shift menu 'learn,nolearn,forget,play' '13-8-05 key repeat delay for < > pause 130 was pause 100 ' dbldo lcd text added '============================================================== 'New '--- ' 'CommonRam: lcmnds 13 'Variables: 'Routines: Cmndlearner '============================================================== 'Milford IRremote - trained on keys 1,2,3,4,5,6,7,8 'PicAxe needs no training - uses Sony IR-remote protocol 'The keys are numbered from 1, 'but in the program the commands and command pages are numbered 'from 0 'on powerup cmndpge=0 'pages are indicated by the two LEDs, red,green = 00,01,10,11 'the commands in page 0 latch until a new command is sent 'so to stop Hextor press key5 to send the page 0 command ' ' cmnd cmndpge=0 cmndpge=1 cmndpge=2 cmndpge=3 'key1 0 Forward Sit Grip Pick RUN0 'key2 1 Backward Up Grip Down Do Default 'key3 2 Rightturn Midd Grip Open 'key4 3 Leftturn Kill Grip Close uswander ' ' LEDs 'key5 00 cmndpge=0 'key6 01 cmndpge=1 'key7 10 cmndpge=2 'key8 11 cmndpge=3 '============================================================== ' 'Ultrasonic-behaviour name-table program2 '---------------------------------------- US_null CON 0 US_sitcorner CON 1 US_beg CON 2 US_hello CON 3 US_wander CON 4 US_user1 CON 5 US_user2 CON 6 US_user3 CON 7 US_user4 CON 8 US_last CON 8 'last routine ' 'Utilities name-table '--------------------- U_KlcdCon CON 1 U_KirCon CON 2 U_last CON 2 'last routine ' '-------------------------------------------------------------- 'LCD commands. 'For more detailed information see the ILM-216 User Manual. 'Function ASCII '-------- ----- 'Null .................................... 0 'Cursor home ............................. 1 'Hide cursor ............................. 4 'Show underline cursor ................... 5 'Show blinking-block cursor .............. 6 'Bell (not implemented with Hextor LCD) .. 7 'Backspace ............................... 8 'Horezontal tab (4 columns) .............. 9 'Smart linefeed (cursor down one line) ... 10 'Vertical tab (cursor up one line) ....... 11 'Formfeed (clear screen) ................. 12 'Carriage return ......................... 13 'Backlight on ............................ 14 'Backlight off ........................... 15 'Accept cursor position entry ............ 16 ' 64 is the start of the first line ' 80 is the start of the second line 'Format right aligned text ............... 18 'Escape (ESC; start multipart instruction) 27 ' ------------------- ' | LCD | ' ------------------- 'LCD keys - bit0 bit1 bit2 bit3 '-------------------------------------------------------------- '--------- LCD messages - finish each message with Null ------- duserprog DATA (8) dbtxt DATA 12,4,16,80,"back < > do ",0 dbldo DATA 16,92,"do&l",0 'learn do dmK DATA 1," FBRLSUMZPDOCNQT",0 dmIR DATA 12,4,"IR=",16,86,"Cd=",16,80,"back",16,92,"Pg=",0 dmIR0 DATA 16,72,"FBRL ",0 dmIR1 DATA 16,72,"SUMK ",0 dmIR2 DATA 16,72,"PDOC ",0 dmIR3 DATA 16,72,"0DxWndr",0 dmIRw DATA 12,"Leting IR settlewait 5 secs",0 dmlearn DATA 1,"learn ",0 dmnolearn DATA 1,"nolearn",0 dmplay DATA 1,"play ",0 dmsave DATA 1,"save ",0 dmnew DATA 1,"new ",0 dmallnew DATA 1,"allnew ",0 dmdo DATA 1,"do ",0 dmforget DATA 1,"forget ",0 '-------------------------------------------------------------- 'learned moves - end of list is "z", same as A_Acts dlearned DATA "z" '-------------------------------------------------------------- 'common RAM '0 program to return to - all '1 Program option - Activity to do, USrules to do, Options '2 current Utility routine '3 usyawn0 - US-behaviour '4 usyawn1 - US-behaviour '5 irin - current IR value on change of pgm '6 oldbtn - current button on change of pgm '7 mopts - active menu OAUIP '8 menc - active menu displayed choice '9 mendo - selected choice '10 flags - various flag bits ' bit0=irwatch - 0=>ignore IR signal, 1=>act on it ' bit1=useLEDs - 0=>ignore LED cmnds, 1=>enable LEDs ' (for if pins remapped) ' bit2=usefeelers - 0=>ignore feelers ' bit3=useUS - 0=>don't run US routines ' bit4=warmIR - 1=>IR chip needs no warmup time ' bit7=flagsvalid - 0 after download, 1->ok '11 Dprog - Default program to run '12 Dmenc - Default option '13 lcmnds - number of learned BOScmnds Prog7LCDmenu '14 BOSver - BOS version '15 BOScmnd for Learning and Playing - to pass between Prog5 and Prog7 '16 Act - current Act being Learned/Played - used by Prog5/7 '17 pAct - current step in Act - used by Prog5 '18 IRpage 'Note there is no test for the stack being too big, beware of 'the stack growing down through RAM variables! '60 down sequence stack '61 sequence stack pointer '62 letterbox for push and pop '63 active program number used by BS2Sx '-------------------------------------------------------------- BOStx CON 0 'pin serial to BOS processor BOSrx CON 1 'pin serial from BOS processor epower CON 2 'pin high turns on power to electronics BOShalt CON 3 'pin high halts current BOS move BOSbusy VAR IN4 'pin BOS processor busy => high irrx CON 5 'pin infra red comms in, i96n lcdtx CON 6 'pin to send to LCD lcdrx CON 7 'pin to receive from LCD outRled VAR OUT9 'pin high turns on right green led outLled VAR OUT8 'pin high turns on left red led i96n CON 16624 '9600 baud, 8 bit, no parity, inverted BOScmnd VAR Byte 'byte to send to BOS processor nocmnd CON 15 'Kir - no command pending Uname VAR Byte 'code value of Utility name Prog VAR Byte irin VAR Byte 'infra-red command oldirin VAR Byte 'old infra-red command retprog VAR Byte 'program to return to irentry VAR Byte 'irin on entry to pgm lcdbtns VAR Byte 'button states are in lower nibble btn1state VAR lcdbtns.BIT0 btn2state VAR lcdbtns.BIT1 btn3state VAR lcdbtns.BIT2 btn4state VAR lcdbtns.BIT3 btn VAR lcdbtns.HIGHNIB '0 - 4 current button state oldbtn VAR Nib cmndpge VAR Nib 'Kir command page cmnd VAR Nib 'Kir command useqs VAR cmnd 'current user sequence, KlcdCon nseqslot VAR Nib 'next free sequences slot,KlcdCon menc VAR Byte 'current menu Choice lcdmsg VAR Word 'pointer to current char in text tmpwrd VAR lcdmsg lcdchar VAR Byte 'character to send to LCD flags VAR Byte 'various flags Firwatch VAR flags.BIT0 '1=>watch for IR 'Fuseleds var flags.bit1 'future prog1 'Fusefeel var flags.bit2 'future prog1 'FusekUS var flags.bit3 'future prog2 FwarmIR VAR flags.BIT4 'write6,write7 Flearn VAR flags.BIT5 'write7 Fflagsvalid VAR flags.BIT7 cli VAR Nib 'CmndLearn index cmnds VAR Byte 'number of cmnds in sequence lcmnds VAR Byte 'curent number of learned cmnds pcmnd VAR Byte 'Play pointer to cmnd tmpmem VAR Word 'start of temp memory ie short term memory seqmem VAR lcdmsg 'start of sequence memory Ftemp VAR Bit init: HIGH epower 'keep electronics on GET 1,Uname PUT 1,0 'so we don't do it again and ... GET 10,flags 'IRwatch,warmIR GET 13,lcmnds '0 on power-up IF Uname<>0 THEN brnch 'something to do GET 2,Uname IF Uname<>0 THEN brnch 'we have unfinished business GOTO RUN0 'nothing else to do brnch: IF Uname>U_last THEN RUNX 'back to calling pgm BRANCH Uname,[RUN0,KlcdCon,KirCon] DEBUG "bad branch" GOTO RUN0 'if invalid branch '-------------------------------------------------------- KlcdCon: 'Keys-lcd Control menc =0 lcdmsg =dbtxt :GOSUB lcd 'cls, write keys lcdmsg =dmK :GOSUB lcd 'write BOScmnds IF Flearn=0 THEN Klcdit lcdmsg =dbldo :GOSUB lcd 'write learn do Klcditp: PAUSE 130 'key repeat delay for < > Klcdit: LOOKUP menc+1,[" FBRLSUMZPDOCNQT"],BOScmnd LOOKUP menc,[" FBRLSUMZPDOCNQT"],lcdchar 'got to type the char before the one we want to indicate 'so the cursor ends up under the one to indicate. SEROUT lcdtx,i96n,[5,16,(64+menc),lcdchar] Klcdb: GOSUB askbtns IF btn=1 THEN Klcd1 '"back" IF btn=2 THEN Klcd2 '" < " IF btn=3 THEN Klcd3 '" > " IF btn=4 THEN Klcd4 '" do " GOTO Klcdb Klcd1: SEROUT lcdtx,i96n,[12,4] '"back" GOSUB askbtnsw GOTO RUN0 Klcd2: menc =menc -1 MAX 14 '" < " GOTO Klcditp Klcd3: menc =menc +1 '" > " IF menc<15 THEN Klcditp menc =0 'last char so back to first GOTO Klcditp Klcd4: IF btn3state=1 THEN CmndLearner '">"+"do" GOSUB askbtns IF btn<>0 THEN Klcd4 'wait until finger off button GOSUB tellBOSc '"do" GOTO Klcdb 'rest once only '-------------------------- CmndLearner: 'EEPROM 0cmnds0, 1cmnds1, 2cmnds2,3cmnds3,4cmnds4,5cmnds5,6tmpmem.lo,7tmpmem.hi lcdmsg =dbtxt :GOSUB lcd 'cls, write keys tmpmem =dlearned nseqslot=0 _clrduseqs: READ nseqslot,cmnds tmpmem =tmpmem +cmnds 'cmnds includes final "z" nseqslot =nseqslot +1 IF cmnds<>0 AND nseqslot<8 THEN _clrduseqs 'only 8 slots nseqslot =nseqslot -1 'cmnds now =0 so nseqslot is first free sequence useqs =nseqslot 'number of sequences 1,2,.... GOSUB askbtnsw 'wait till buttons clear cli =0 _cldisp:LOOKUP cli,[dmlearn,dmnolearn,dmplay,dmsave,dmnew,dmallnew,dmdo,dmforget],lcdmsg :GOSUB lcd IF cli<6 THEN _clkeys SEROUT lcdtx,i96n,[16,70,DEC1 useqs] _clkeys:GOSUB askbtnsw IF oldbtn=1 THEN KlcdCon '"back" IF oldbtn=2 THEN _clprev '" < " IF oldbtn=3 THEN _clnext '" > " IF oldbtn=4 THEN _clDo '" do " GOTO _cldisp _clprev: IF cli<6 THEN _deccli IF useqs=0 OR useqs=1 THEN _deccli 'no sequence or only one useqs =useqs -1 MIN 1 'otherwise decrement GOTO _cldisp _deccli: IF useqs<>0 THEN _deccli7 _deccli5: cli =cli MIN 1 -1 MAX 5 :GOTO _cldisp 'so if we forget1 then do0 doesn't appear _deccli7: cli =cli MIN 1 -1 MAX 7 :GOTO _cldisp _clnext: IF cli<6 THEN _inccli IF useqs=nseqslot THEN _inccli useqs =useqs +1 GOTO _cldisp _inccli: IF useqs<>0 THEN _inccli7 _inccli5: cli =cli +1 MAX 5 :GOTO _cldisp _inccli7: cli =cli +1 MAX 7 :GOTO _cldisp _clDo: BRANCH cli,[_cllon,_clloff,_clplay,_clsave,_clnew,_clallnew,_clsdo,_clsforget] '--------------------- _cllon: Flearn =1 GOTO KlcdCon '--------------------- _clloff: Flearn =0 GOTO KlcdCon '--------------------- _clPlay: DEBUG" Play" seqmem =tmpmem _clPdo: DEBUG" playdo" DEBUG?seqmem Ftemp =Flearn Flearn =0 'don't learn while playing pcmnd =0 _clPread: READ (seqmem+pcmnd),BOScmnd DEBUG?pcmnd,BOScmnd IF BOScmnd="z" THEN _clPend SEROUT lcdtx,i96n,[16,72,BOScmnd] GOSUB tellBOSc :PAUSE 200 'so we can see first displayed BOScmnd pcmnd =pcmnd+1 GOTO _clPread _clPend: Flearn =Ftemp PAUSE 500 'so we can see last displayed BOScmnd GOTO CmndLearner '--------------------- _clsave: DEBUG" save",?useqs cmnds =lcmnds +1 'leave room for final "z" WRITE nseqslot,cmnds nseqslot =nseqslot +1 'next sequence slot tmpmem =tmpmem +cmnds 'new tmpmem position lcmnds=0 'nothing learned PUT 13,lcmnds WRITE (tmpmem+lcmnds),"z" '"z" at position0 GOTO CmndLearner '--------------------- _clnew: lcmnds =0 PUT 13,lcmnds WRITE (tmpmem+lcmnds),"z" GOTO KlcdCon '--------------------- _clallnew: lcmnds =0 PUT 13,lcmnds FOR useqs=0 TO 7 WRITE useqs,0 NEXT tmpmem =dlearned WRITE (tmpmem+lcmnds),"z" GOTO CmndLearner '--------------------- _clsdo: GOSUB _clfindseq 'find seqmem for useq GOTO _clPdo '--------------------- _clsforget: 'works like FORTH forget DEBUG" forget" GOSUB _clfindseq FOR menc=(useqs -1) TO (nseqslot -1) 'use menc as scratchpad WRITE menc,0 NEXT WRITE seqmem,"z" lcmnds =0 GOTO CmndLearner '--------------------- _clfindseq: DEBUG" find" 'find seqmem for useq seqmem =dlearned menc=0 'use menc as scratchpad _clfs1: READ menc,cmnds DEBUG?menc,?cmnds menc =menc +1 IF menc=useqs THEN _clfret: seqmem =seqmem +cmnds GOTO _clfs1 _clfret: DEBUG?seqmem RETURN '-------------------------------------------------------- KirCon: 'Keys IR Control 'set irwatch to on in case Kircon is default DO Firwatch =1 PUT 10,flags IF FwarmIR=1 THEN ncmnd lcdmsg =dmIRw :GOSUB lcd PAUSE 5000 'wait for IR chip to settle FWArmIR =1 PUT 10,flags ncmnd: cmnd=nocmnd BOScmnd ="z" 'OTHERwise we inherit "V" lcdmsg =dmIR :GOSUB lcd 'write IR screen GET 18,cmndpge '0 at poweron GOTO Kirpagecmnd 'make sure LEDs are correct Kir: oldirin =irin GOSUB askbtns IF btn=1 THEN RUN0 '"back" button PAUSE 20 'IR gives wrong results if asked too often Kirops: GOSUB irget 'look at IR stream SEROUT lcdtx,i96n,[16,67,DEC2 irin,16,89,BOScmnd,16,95,DEC1 cmndpge] LOOKUP cmndpge,[dmIR0,dmIR1,dmIR2,dmIR3],lcdmsg :GOSUB LCD IF irin > 8 THEN Kir 'non valid response IF irin=0 THEN Kirdo '0 is idle value IF irin=oldirin THEN Kirdo 'only process new IRvalues Kirnew: IF irin<5 THEN Kircmnd cmndpge =irin -5 'cmndpge 0,1,2,3 GOTO Kirpagecmnd 'act on page cmnd Kircmnd: cmnd =irin -1 'new cmnd =0,1,2,3 'process cmnd and cmndpge into instructions for BOS BRANCH cmndpge,[Kirmove,Kirpose,Kirgripper,Kirprogs] '------ Kir leaves ----- Kirdo: IF BOScmnd="z" THEN Kir IF BOSbusy=1 THEN Kir GOSUB tellBOSc IF cmnd<>nocmnd THEN Kir BOScmnd ="z" 'so we only tell BOS once GOTO Kir Kirmove: 'page0 LOOKUP cmnd,["FBRL"],BOScmnd 'since cmnd is not cleared these commands latch GOTO Kir Kirpose: 'page1 LOOKUP cmnd,["SUMK"],BOScmnd cmnd =nocmnd GOTO Kir Kirgripper:'page2 LOOKUP cmnd,["PDOC"],BOScmnd cmnd =nocmnd GOTO Kir Kirprogs:'page3 IF cmnd=0 THEN RUN0 IF cmnd=1 THEN Kirdefault IF cmnd=3 THEN Kiruswander GOTO Kir Kirpagecmnd: outRled =cmndpge.BIT1 'cmndpge to LEDS p8,p9 outLled =cmndpge.BIT0 BOScmnd ="z" 'new page, so old cmnd is invalid GOTO Kir '------------- RUN leaves ---------------------- Kirdefault: GET 63,Prog 'put this Prog in arg.lownib(3) PUT 0,Prog PUT 5,irin PUT 18,cmndpge 'save current page '11 Dprog - Default program to run '12 Dmenc - Default option GET 12,cmnd PUT 1,cmnd GET 11,Prog RUN prog '-------------- Kiruswander: PUT 1,US_wander GET 63,Prog 'put this Prog in arg.lownib(3) PUT 0,Prog PUT 5,irin PUT 18,cmndpge 'save current page RUN 2 '-------------- RUN0: GET 63,Prog 'put this Prog in arg.lownib(3) PUT 0,Prog PUT 2,0 'clear Uname in CommonRam PUT 6,oldbtn RUN 0 '-------------- RUNX: GET 0,retprog GET 63,Prog 'put this Prog in arg.lownib(3) PUT 0,Prog PUT 1,0 'no info on what to do PUT 2,0 'clear Uname in CommonRam RUN retprog 'go back to calling program '------------- subroutines --------------------- lcd: READ lcdmsg,lcdchar IF lcdchar=0 THEN lcdret 'if 0 then end of msg SEROUT lcdtx,i96n,[lcdchar] lcdmsg =lcdmsg +1 'point to next character GOTO lcd lcdret: RETURN '-------------------- askbtnsw: 'ask and wait until finger off button ->oldbtn btn =0 _ab: oldbtn =btn GOSUB askbtns IF btn<>0 THEN _ab RETURN '-------------------- askbtns: lcdbtns =0 'set a default value SEROUT lcdtx,i96n,[27,"K0"] 'ask LCD for button status SERIN lcdrx,i96n,200,nolcd,[lcdbtns] 'get byte nolcd: btn =NCD lcdbtns.LOWNIB '0 - 4 RETURN '-------------------- irget: 'listen to InfraRed co-processor irin =0 'set to idle value IF Firwatch=0 THEN irret SERIN irrx,i96n,100,irret,[irin] 'valid 0 - 8 irin =irin & $F 'mask high nibble timing data irret: RETURN '-------------------- tellBOSc: 'used for the initialisation beeps & KeyCon PAUSE 10 'give the BOS time to go into receive mode IF BOSbusy=1 THEN tellBOSc 'wait until BOS not busy SEROUT BOStx,i96n,[BOScmnd] DEBUG BOScmnd IF Flearn=0 THEN _tBOSc_rtn WRITE (tmpmem+lcmnds),BOScmnd lcmnds =lcmnds +1 :PUT 13,lcmnds WRITE (tmpmem+lcmnds),"z" _tBOSc_rtn: RETURN '------------------------ end program -------------------------