; Micro-Controller BRAIN for Nervous Network control ; by Terry Newton Last Modified 8/22/97 ; PIC16C56 source code for Parallax assembler ; Work in progress, not for permanent burn ; ; Control Circuit... ; ; .---*----*---*------------*-------*-------*-----------> + ; | _|_ _|_ | 2.2u | _|_ | ; .-----. | |22K||22K| | .--||-----' |4.7| .---|--< ra1 photo R (+) ; .--|1 |--' |___||___| | | |_K_| | .-|--< ra0 photo L (+) ; *--| |- | | | | .-----. | | | | .1u ; *--|24C65|------*----|---|--|--------|1 |--|---*-|-|--||--. ; *--| |-----------*---|--|--------| |--|-----*-|--||--*----> - ; | `-----' | | -| |--*-||-. | .1u _|_ ; _|_ *--|--------| |- 27p_|_ | ; | *--------| PIC |----------' ; | _|_ .---| |----820K------> rb7 Node 4 ; PIC = PIC16C56 windowed | .-----|---| |----820K------> rb6 Node 3 ; version programmed w/ | | .---|---| |----820K------> rb5 Node 2 ; this code | | | .-|---| |----820K------> rb4 Node 1 ; | | | | | `-----' ; .--|<|---|-|-|-*-|-----*---------------< rb3 Feeler R (-) ; From >---*--|<|---|-|-*---|---*-|---------------< rb2 Feeler L (-) ; Rear Switch | `-----|---|-|--|<|--*-------> rb1 Reverse out ; *--100K-|---*-|-|>|-. `-|>|-*-< existing rev sig ; `--100K-|-----*-|>|-*-------' (from rev timer) ; .-|<|--2.2K-*---|<|---------------> rb0 to reset sw ; _|_Status LED (to reset timer) ; ; Underlying walker circuit... ; ; NOTE: This is a version of the Nervous Network, invented and ; internationally patented by Mark Tilden. Commercial usage is prohibited ; unless arrangements are made with the patent holder . ; ; + ; | .-> To cpu ; Npn >|-----. Rev.Clr<--. .---|>|--*- + .----. | ; |e.---. | | /| | .----. | .--|1.5M|--* Rear ; .------*-|470|-*--------. *---O< |--*-|1.5M|-' | `----' | Switch ; | |e`---' | | | \| | `----' *---||-----*---O|_ ; | Pnp >|-----' | | 2.2u | .----. | 47u + O| \ ; | _|_ .---|<|---|-----' .--||--*-| 10 |---' | _|_ ; | | | _|_ `----' .-----|< Npn ; | .12u |1 |\ | .12u 2 |\ | .---.e| ; | .--||--*---| >O--*---. .--||--*---| >O---*--*-|470|-*-----. ; | | _|_ |/ | | _|_ |/ | | `---'e| | ; | | |1.5| 74HCT14 | | |1.5| | `-----|< Pnp | ; | | |_M_| | | |_M_| | _|_ | ; | | _|_ | | _|_ | | ; | | | `------. | | ; | | CD4016 by 2 .---|----------|----------' | ; | | .----------|---|----------|-. | ; | | .-|-*-|><|---* `-*-|><|---* | + | ; + | | *-|--' | | `---|-* _|_ + ; Rear \ / | `-|><|-. | `-|><|-. | | |100| Front ; Motor \ | `--|-|-*------' | | | |_K_| + Motor ; - / \ | .-|><|-|-' | .-|><|-|-' | .----. | e| - ; | | | | | `--|---*---|--' | *-|220K|-*--|< Pnp | ; | | `-|-*-|><|-* | *-|><|-* | `----' | | ; | | `----' ` | | | `-|---*------. | | ; | | .----.`---|---|------|----------|-. | + | ; | | .-|100K|----*---|------|----------|-|----' | | ; | | _|_`----' .-----' .----' | | .-----|< Npn | ; | | .12u 3 |\ | | .12u 4 |\ | | | .---.e| | ; | `--||--*---| >O--* `--||--*---| >O-|-*--*-|470|-*-----' ; | _|_ |/ | _|_ |/ | | `---'e| ; | |1.5| | |1.5| .--' `-----|< Pnp ; | |_M_| | |_M_| | _|_ ; | + _|_ | _|_ | .-|>|-. ; | | | | _|_ | 2.2u ; | Npn >|-----. | Reverse >----' *--||--*-- + ; | |e.---. | | /| | _|_ ; `------*-|470|-*--------' Rev.Sw.out <------O< |---*--. |390| ; |e`---' | \| _|_ | |___| ; Pnp >|-----' |1.5|| +A| Front ; _|_ |_M_|| O|_ Switch ; Photocells _|_ *---O| \ ; Power and Sensors... .--<+A (390) | ; (optional) + source | _ RST>-' Feeler ; Solar ____ ____ o *--|_|--> L \ Switches/ ; Cells | | | | | 5.1vZD | _ Photo \ / ; .--*--|- +|--|- +|--*---*--|<|-. `--|_|--> R |<-*->| ;Power| | |____| |____| | | 47u | .------------' _|_ | ; O | 3.6V Battery | `--||--* L <---*-- 10 --||-. | ; \ | | | | + | _|_ Feeler 47u | | ; O *---| | | | | |----* R <---*-----------|------' ; _|_ | | | | `-- 100 --O Ext `-- 10 --||-* ; *-- 68 -----*--------- 100 --O Charge 47u_|_ ; | ^^ | Npn.-100-->RST ; `----|>|----' Rev.Clr>--10K--|< ; charge LED e|_ ; device PIC16C56, RC_OSC, WDT_ON, PROTECT_OFF reset startup ; port masks PortAMask = 00001011b ; bit 0-1 inputs, bit 2 out, bit 3 in PortARst = 00001000b ; for clearing analog ins PortBMask = 00001101b ; bit 1 4-7 outs, bits 2-3 ins, 0=in PortBHiZ = 11111101b ; for hi-z state (no control) PortBStat = 11111100b ; make bit 0 out for status/reset ; analog inputs, 8 bit resolution (cell to +, .1u to gnd) AnaIn_1 = ra.0 ; L Photo AnaIn_2 = ra.1 ; R Photo ; digital inputs, active low (ground) DigIn_1 = rb.2 ; L Feeler DigIn_2 = rb.3 ; R Feeler ; outputs Reverse = rb.1 ; to 4016 switch active low Node_1 = rb.4 ; Node_2 = rb.5 ; to microcore ins thru Node_3 = rb.6 ; 820K resistors Node_4 = rb.7 ; EffectMax = 60 ; >15, 16 / (Max+1) = max control duty EffectNum = 25 ; total number of control cycles per period ; inputs ThisEnv = 15h LastEnv = 16h ; environment bits feeler_L = 0 ; normally 0, 1 if touching feeler_R = 1 ; same photo_L = 2 ; 000 = equal 110 = R a lot brighter photo_M = 3 ; 100 = R brighter 011 = L a lot brighter photo_R = 4 ; 001 = L brighter 010, 101, 111 = ??? photo_A0 = 5 ; average light level bit 0 photo_A1 = 6 ; average light level bit 1 EnvMask = 01111111b ; mask of available environment bits Analog_1 = 08h ; analog values from photocells Analog_2 = 09h ; unacceptable environment bits... Inhib = 00000011b ; doesn't like feeler ; inhibit bits for remembered actions Inhib1R = 10001000b ; sad if major control, positive bias Inhib2R = 10001000b ; or reverse bits set with no stimulus Inhib3R = 10001000b Inhib4R = 10001001b ; layout of memory records ; bit-7 bit-6 bit-5 bit-4 bit-3 bit-2 bit-1 bit-0 ; ----- ----- ----- ----- ----- ----- ----- ----- ; byte 0 - 1out3 1out2 1out1 1out0 1pola conf2 conf1 conf0 ; byte 1 - 2out3 2out2 2out1 2out0 2pola dura2 dura1 dura0 ; byte 2 - 3out3 3out2 3out1 3out0 3pola 0 1 0 ; byte 3 - 4out3 4out2 4out1 4out0 4pola xxxxx look revrs ; ; out0-3 16 levels of pwc resistance, 0000 = hi-z 1111 = full on ; 1000 = half on, pola 0 ground bias 1 hot bias ; conf0-2 confidence number 0-7 (or 0-3) ; dura0-2 duration of move 000 short, 111 long ; reverse bit 1=reverse (flip before outputing to pull low for reverse) ; look bit 1=next move bad Action1 = 17h ; copy of memory record Action2 = 18h ; (4 bytes) Action3 = 19h ; Action4 = 1Ah ; AOutMask = 11111000b ; with reverse bit ActMask = 11110000b ; just action bits PolaBit = 3 PolaLimit = 00011000b ; max action if polarity plus ConfByte = Action1 ConfMask = 00000111b ; confidence 0 to 7 ConfMrev = 11111000b ; reverse of it DuraByte = Action2 DuraMask = 00000111b ; duration 0 to 7 DuraMrev = 11111000b ; reverse of it RevByte = Action4 RevBit = 0 Look = Action4.1 ; for lookahead TagByte = Action3 TagMask = 00000111b ; 'been here' pattern TagValue = 00000010b ; 010 = valid memory Confidence = 1Bh Duration = 1Ch Flags = 1Dh Happy = Flags.0 ; happy if set, sad if not Changed = Flags.1 ; set if action bytes changed NetRunning = Flags.2 ; set if net is running LastHappy = Flags.3 ; last state of being GammaUp = Flags.4 ; set if confidence maxes GammaDown = Flags.5 ; set if confidence bottoms out GammaC = 1 ; starting confidence for gamma memories Temp = 1Eh CycleCount = 1Fh ; time to shutdown WakeUpBits = 01111111b ; environment bits to look at for waking up StatusLED = rb.0 ; for debugging, hiz or high ResetSig = rb.0 ; double use the pin, low to reset ; these set to top of 8K chip, alter if smaller eeprom used ; (happens to be an 8K but wastes a TON of space, 1K would do) Ebyte0 = 00011100b ; location of memory byte 0 Ebyte1 = 00011101b ; location of memory byte 1 Ebyte2 = 00011110b ; location of memory byte 2 Ebyte3 = 00011111b ; location of memory byte 3 Econf = Ebyte0 Etag = Ebyte2 VarA = 0Ah ; stolen vars from ee routines VarB = 0Bh ; values destroyed when accessing VarC = 10h VarD = 11h VarE = 12h VarF = Duration ; borrow this variable org 000h ; (all called subroutines must fall in page 0, so this stuff's first) ; EEPROM routines modified from Microchip application note AN558 ; bitin and bitout routines are coded in-line to permit write and ; read routines to be called without overflowing stack. Also modified ; some of the timing routines and dropped several nops. Using with ; RC osc. 4.7K and 27pF Delays are approximate and not calibrated! ; Any bugs are my own (the following code is in Microchip format) ; EEPROM variables... (EE data = RA.3, clock = RA.2) statby = 03h eeport = 05h ; port A eeprom = 0Ah bycnt = 0Bh addr = 0Ch addr1 = 0Dh datai = 0Eh datao = 0Fh txbuf = 10h count = 11h bcount = 12h loops = 13h loops2 = 14h di = 3 do = 2 sdata = 3 sclk = 2 outmask = 00000000b inmask = 00001000b ; wait routine - waits approx loops milliseconds wait movlw 150 movwf loops2 wait2 nop nop nop decfsz loops2 goto wait2 decfsz loops goto wait clr wdt ; convenient ret ; generate start bit bstart bsf eeport, sdata movlw outmask tris eeport bcf eeport, sclk nop bsf eeport, sclk nop nop bcf eeport, sdata nop nop bcf eeport, sclk nop ret ; generate stop bit bstop bcf eeport, sdata movlw outmask tris eeport bcf eeport, sdata nop nop bsf eeport, sclk nop nop bsf eeport, sdata nop bcf eeport, sclk nop nop ret ; transmit byte in txbuf tx movlw 8 movwf count txlp bcf eeprom, do btfsc txbuf, 7 bsf eeprom, do movlw outmask tris eeport btfss eeprom, do goto txlp1 bsf eeport, sdata goto txlp2 txlp1 bcf eeport, sdata txlp2 bsf eeport, sclk nop nop nop bcf eeport, sclk rlf txbuf decfsz count goto txlp bsf eeprom, di movlw outmask tris eeport bsf eeport, sclk nop nop btfss eeport, sdata bcf eeprom, di bcf eeport, sclk ret ; receive byte into datai rx clrf datai movlw 8 movwf count bcf statby,0 rxlp rlf datai bsf eeprom, di movlw outmask tris eeport bsf eeport, sdata bsf eeport, sclk nop nop nop btfss eeport, sdata bcf eeprom, di bcf eeport, sclk btfsc eeprom, di bsf datai,0 decfsz count goto rxlp ret ; get byte from EEPROM into datai rbyte call bstart movlw 10100000b movwf txbuf call tx movf addr1,w ; high address movwf txbuf call tx movf addr,w ; low address movwf txbuf call tx call bstart movlw 10100001b movwf txbuf call tx call rx call bstop ret ; write byte in datao to EEPROM wbyte call bstart movlw 10100000b movwf txbuf call tx movf addr1,w movwf txbuf call tx movf addr,w movwf txbuf call tx movf datao,w movwf txbuf call tx call bstop movlw 10 movwf loops call wait ret ; ========== Oh what a happy day to code my bot brain! ; BRAIN code Should the floodgates of reality pour not ; ========== Might I code the seeds of intelligence... ; (ahhh... it sort of works now!) ; link to getenvironment sub in page 3 (only 0 and 2 can be called) GetEnvironment ljmp GetEnvL ; main code starts here - this is where reset goes to startup jb statby.3, start0 ljmp Sleep3 ; timeout from sleep start0 mov OPTION, #00001111b ; int rtc, max wdt (!OPTION for SPASM) mov !ra, #PortAMask ; set the A port direction bits mov !rb, #PortBHiZ ; and the B port bits to no control setb Reverse ; forward march! lcall RestartNet ; just in case, my walker doesn't ; always start by itself mov Temp, #15 start1 mov loops, #200 call wait djnz Temp,start1 ; wait a few seconds setb Happy ; nice to start out in a good mood call GetEnvironment ; look around for the first time mov w, ThisEnv and w, #01100000b ; just the average bits lcall LEDflash ; for debugging clc mov CycleCount, Analog_1 ; use photocells to get on-time add CycleCount, Analog_2 ; average the two cells rr CycleCount rr CycleCount rr CycleCount ; max 32 moves and CycleCount, #00011111b ; mask off carry bits from rrs cjae CycleCount, #7, mainloop mov CycleCount, #7 ; at least 7 moves mainloop clr wdt dec CycleCount cjne CycleCount, #255, main1 ljmp Sleep ; go to sleep if cycles exausted main1 mov Addr, ThisEnv ; form memory address... mov Addr1, #Ebyte0 call rbyte mov Action1, datai mov Addr1, #Ebyte1 call rbyte mov Action2, datai mov Addr1, #Ebyte2 call rbyte mov Action3, datai mov Addr1, #Ebyte3 call rbyte mov Action4, datai ; read memory from eeprom clrb Changed ; reset changed flag (determines if memory ; needs updating - to save wear and tear) mov Temp, TagByte and Temp, #TagMask cjne Temp,#TagValue, GetRand ; jump if invalid memory mov w, ConfByte and w, #ConfMask jnz PerformMove ; jump if confidence > 0 GetRand ; reload Action1 - Action4 from the RTCC lcall rtshift mov Action1, VarB lcall rtshift mov Action2, VarB lcall rtshift mov Action3, VarB lcall rtshift mov Action4, VarB ; limit effect if positive jnb Action1.PolaBit, GR1 and Action1, #PolaLimit GR1 jnb Action2.PolaBit, GR2 and Action2, #PolaLimit GR2 jnb Action3.PolaBit, GR3 and Action3, #PolaLimit GR3 jnb Action4.PolaBit, GR4 and Action4, #PolaLimit GR4 movb RevByte.RevBit, RTCC.1 ; random reverse lcall rtshift ; just for random wait mov w, RTCC and w, #DuraMask or DuraByte, w ; random duration or TagByte, #TagValue ; mark as a valid memory setb Changed ; leave at confidence 0 PerformMove ; try to control the net mov duration, DuraByte and duration, #DuraMask mov confidence, ConfByte and confidence, #ConfMask movb Reverse,/RevByte.RevBit ; update reverse out PLoop mov VarA, #EffectNum ; cycles per period Ploop1 mov !rb, #PortBHiZ ; start each cycle all hiz mov VarE, #PortBHiZ ; save since !rb cant be or'd directly mov Temp, #EffectMax ; defined duty cycle PLoop2 mov VarB, Action1 swap VarB ; put effect bits into low nibble and VarB, #15 ; get rid of high bits cjne VarB,Temp, PL2A ; go if VarB <> temp (countdown) and VarE, #11101111b mov !rb, VarE ; turn on node pin movb Node_1, Action1.PolaBit ; set output state and VarE, #PortBStat mov !rb, VarE setb statusLED PL2A mov VarB, Action2 ; do action2-4 same way swap VarB and VarB, #15 cjne VarB,Temp, PL2B and VarE, #11011111b mov !rb, VarE movb Node_2, Action2.PolaBit and VarE, #PortBStat mov !rb, VarE setb statusLED PL2B mov VarB, Action3 swap VarB and VarB, #15 cjne VarB,Temp, PL2C and VarE, #10111111b mov !rb, VarE movb Node_3, Action3.PolaBit and VarE, #PortBStat mov !rb, VarE setb statusLED PL2C mov VarB, Action4 swap VarB and VarB, #15 cjne VarB,Temp, PL2D and VarE, #01111111b mov !rb, VarE movb Node_4, Action4.PolaBit and VarE, #PortBStat mov !rb, VarE setb statusLED PL2D mov loops, #1 call wait ; delay djnz Temp, Ploop2 ; check for next effect value djnz VarA, Ploop1 ; do enough times to have an effect jb ThisEnv.Feeler_L, PL3A jb ThisEnv.Feeler_R, PL3A ; go if already knows jnb DigIn_1, PL3B jnb DigIn_2, PL3B ; short duration if something touches PL3A dec Duration cjne Duration,#255, Ploop ; loop duration+1 times PL3B mov !rb, #PortBHiZ ; back to no control ; see if net is still running.... mov Temp, #75 ; check for 75 cycles clrb NetRunning ChkNet jnb Node_1, ChkNet1 sb Node_3 setb NetRunning ; if opposing node not on, set flag ChkNet1 jnb Node_2, ChkNet2 sb Node_4 setb NetRunning ChkNet2 mov loops, #40 call wait ; delay each cycle (total about 3 seconds) djnz Temp, ChkNet jb NetRunning, NetOK ; go if running lcall RestartNet ; restart network NetOK ; evaluate the results of last move mov LastEnv, ThisEnv ; save environment for reference later setb Happy call GetEnvironment ; look around (clr happy if not cool) ; evaluate last action if last move was good jnb LastHappy, P3 ; go if in response to something movb LastHappy, Happy ; save this environment state jb Look, P3 ; no move critic if look bit set ; clear happy bit if any action inhibit bits set mov w, Action1 and w, #Inhib1R sz clrb Happy mov w, Action2 and w, #Inhib2R sz clrb Happy mov w, Action3 and w, #Inhib3R sz clrb Happy mov w, Action4 and w, #Inhib4R sz clrb Happy jmp P3A P3 movb LastHappy, Happy ; save environment state clrb Look ; set look bit to happy flag sb Happy ; (maybe it'll help deal with setb Look ; things about to happen...) P3A ; (arranged to *not* save results of action inhibits) mov VarE, Confidence ; save value for comparing clrb GammaUp clrb GammaDown jb Happy, Pinc ; if happy increase confidence mov w, #11111111b lcall LEDflash ; solid flash if not happy dec Confidence ; if not happy lower confidence csne Confidence, #0 setb GammaDown ; set if going from 1 to 0 cjne Confidence, #255, P4 clr Confidence ; down to 0 jmp P4 Pinc inc Confidence csne Confidence, #ConfMask setb GammaUp ; set if going from max-1 to max cjne Confidence, #ConfMask+1, P4 mov Confidence, #ConfMask ; up to max (3 or 7) P4 cse Confidence, VarE setb Changed ; set if confidence changed ; rewrite to lastenv if Changed and ConfByte,#ConfMrev ; mask off confidence or ConfByte,Confidence ; save new confidence mov Addr, LastEnv ; form memory address from previous... mov Addr1, #Ebyte0 mov datao, Action1 call wbyte mov Addr1, #Ebyte1 mov datao, Action2 call wbyte mov Addr1, #Ebyte2 mov datao, Action3 call wbyte mov Addr1, #Ebyte3 mov datao, Action4 call wbyte ; check for Gamma Action and loop jb GammaUp, chkG1 jb GammaDown, chkG1 ljmp mainloop chkG1 ljmp Gamma ; do gamma (page3) if either bit set ; page 2 code org 230h ; sub for restarting net using reset 'neuron' RestartNet mov !rb, #PortBStat ; make bit 0 out clrb ResetSig ; activate reset circuit mov loops, #255 lcall wait ; for a bit mov !rb, #PortBHiZ ; and let go lset 100h ret ; sub for loading random move, return in VarB rtshift ; randomize using photo inputs mov !ra, #PortARst ; configure A-in pins as outputs clrb AnaIn_1 ; discharge caps clrb AnaIn_2 ; by pulling low mov loops, #20 lcall wait ; wait about 20 ms lset 200h mov !ra, #PortAMask ; back to input state rtsh1 jb AnaIn_1, rtsh2 jb AnaIn_2, rtsh2 clr wdt jmp rtsh1 ; hang until a photo goes high rtsh2 mov VarB, RTCC ; get rtcc rl VarB rl VarB rl VarB ; shift xor VarB, RTCC ; and scramble and VarB, #AOutmask ; return 5 outvalue bits, rest 0 lset 100h ret ; sleep mode - stop net cycling and wait until disturbed ; mainly to extend battery life, it's not a true sleep mode ; more like wait and watch (helpful in debugging sensors too) Sleep jnb Happy, NoSleep ; no sleeping if not happy mov !rb, #PortBMask setb Node_1 setb Node_2 setb Node_3 setb Node_4 mov Temp, #15 ; hold high about 3 seconds Sleep1 mov loops, #200 ; that should stop cycling lcall wait lset 200h djnz Temp, Sleep1 mov !rb, #PortBHiZ ; let go, net stopped lcall GetEnvironment lset 200h and ThisEnv, #WakeUpBits ; bits to trigger on mov LastEnv, ThisEnv ; save current environment Sleep2 mov option, #00001110b ; about a second sleep ; go to sleep Sleep3 lcall GetEnvironment lset 200h and ThisEnv, #WakeUpBits ; bits to trigger on cje ThisEnv, LastEnv, Sleep2 ; hang until something changes setb statby.3 ; set in case wdt times out ljmp start0 ; come alive! NoSleep mov CycleCount, #3 ljmp mainloop ; 3 more cycles to get somewhere ; page 3 code org 300h ; linked subroutine to process inputs into useful ThisEnv byte ; this scheme leaves holes, photo_M can't be set unless ; either photo_L or photo_R set, don't care (just makes the ; environment space smaller which is probably a good thing) ; (I think) this part is full of bugs... anything that ; results in a changing environment byte seems to work for ; the 'bot even if the actual bits aren't what I had in mind... GetEnvL mov !ra, #PortARst ; configure A-in pins as outputs clrb AnaIn_1 ; discharge caps clrb AnaIn_2 ; by pulling low mov loops, #30 lcall wait ; wait about 30 ms lset 300h mov !ra, #PortAMask ; back to input state clr Analog_1 clr Analog_2 G1loop dec Analog_1 ; get analog photocell values... clr wdt ; some photocells might need clr wdt ; nop ; to prevent timing out in total darkness ; nop ; This part has been tricky to get ; nop ; just right... larger caps would help jnb AnaIn_1, G1loop ; but add series resistance (100 ohms) G2loop dec Analog_2 ; to prevent possible chip damage clr wdt ; nop ; add/remove nops to adjust photo range ; nop ; (now set to max speed - sensitive photocells) ; nop jnb AnaIn_2, G2loop ; clc ; get rid of l.s.bit ; rr Analog_1 ; of analog in values ; clc ; and divide by 2 ; rr Analog_2 ; (would be noisy anyway) ; heck with shifting... let the bits fall where they may ; for more photo-sensitivity in bright light mov Temp, Analog_1 clc add Temp, Analog_2 ; temp = average of both movb ThisEnv.Photo_A0, Temp.6 movb ThisEnv.Photo_A1, Temp.7 ; average light level clrb ThisEnv.Photo_L clrb ThisEnv.Photo_M ; start with all 0 clrb ThisEnv.Photo_R clc mov VarB, Analog_1 sub VarB, Analog_2 jc GprocA ; more sensitivity... and VarB, #01111100b mov Temp, VarB sz setb ThisEnv.Photo_L ; set photo_L if 1 > 2 by any sig. amount GprocA clc mov VarB, Analog_2 sub VarB, Analog_1 jc GprocB and VarB, #01111100b or Temp, VarB sz setb ThisEnv.Photo_R ; set photo_R if 1 < 2 GprocB and Temp, #01110000b ; keep top bits sz setb ThisEnv.Photo_M ; set photo_M if by large amount movb ThisEnv.Feeler_L, /DigIn_1 ; set feeler_L to inverted dig1 in movb ThisEnv.Feeler_R, /DigIn_2 ; same for feeler_R and ThisEnv, #EnvMask ; get rid of unused environment bits mov w, ThisEnv and w, #Inhib ; bad environment? sz clrb Happy ; if so clear Happy bit lset 100h ; back to page 1 ret ; back to caller with ThisEnv ; Associate good memories - store current move in all locations ; containing same inhibit bits if location is blank anyway Gamma ; visual feedback of association activity jb GammaDown, Gdbg1 mov w, #01010101b ; flicker if gamma up lcall LEDflash lset 300h jmp Gdbg2 Gdbg1 mov w, #11000011b ; two flashes if gamma down lcall LEDflash lset 300h Gdbg2 mov VarF, LastEnv ; get last good environment and VarF, #Inhib ; mask off just inhibit and ConfByte, #ConfMrev ; set confidence field or ConfByte, #GammaC ; to value defined by GammaC clr Addr ; start at address 0 GaLoop ; main gamma loop mov Temp, Addr and Temp, #Inhib jz GaNext ; next addr if no inhibit bits cjne Temp,VarF, GaNext ; next addr if inhib bits not the same jb GammaDown, GaDown ; go to forget routine if down flag set ; must be GammaUp mov addr1, #Etag ; byte with tag value lcall rbyte ; get it lset 300h ; reset page bits and datai, #TagMask ; mask off tag bits cjne datai,#TagValue,GaStore ; ok to use if <>tagvalue mov addr1, #Econf ; byte with confidence lcall rbyte lset 300h and datai, #ConfMask ; mask off confidence bits jnz GaNext ; if valid memory present then next addr GaStore ; save the move mov addr1, #Ebyte0 mov datao, Action1 lcall wbyte mov addr1, #Ebyte1 mov datao, Action2 lcall wbyte mov addr1, #Ebyte2 mov datao, Action3 lcall wbyte mov addr1, #Ebyte3 mov datao, Action4 lcall wbyte lset 300h ; back to page 3 jmp GaNext ; next address ; disassociate bad memories, if existing memory ; confidence <= defined value, make 0 GaDown mov addr1, #Etag ; byte with tag value lcall rbyte ; get it lset 300h ; reset page bits and datai, #TagMask ; mask off tag bits cjne datai,#TagValue,GaNext ; skip invalid memories mov addr1, #Econf ; confidence byte lcall rbyte lset 300h mov Temp, datai and Temp, #ConfMask ; mask off confidence cja Temp,#GammaC, GaNext ; next if confidence > GammaC clr datao lcall wbyte ; forget this memory lset 300h GaNext inc Addr cjb Addr,#EnvMask, GaLoop ; loop thru all addresses ljmp mainloop ; back to mainloop ; ; this in page 2 for debugging org 2A0h ; sub to flash LED with contents of W, on lsb-msb off ; uses loops, loops1, VarC, VarD LEDflash mov VarC, w mov !rb, #PortBStat setb statusLED mov loops,#100 Bwait mov loops2,#255 Bwait2 djnz loops2, Bwait2 djnz loops, Bwait mov !rb, #PortBHiZ mov loops,#100 Bwait3 mov loops2,#255 Bwait4 djnz loops2, Bwait4 djnz loops, Bwait3 mov VarD, #8 LEDfla2 mov !rb, #PortBHiZ jnb VarC.0, LEDfla3 mov !rb, #PortBStat setb statusLED LEDfla3 mov loops,#255 Cwait mov loops2,#255 Cwait2 clr wdt djnz loops2, Cwait2 djnz loops, Cwait rr VarC djnz VarD, LEDfla2 mov !rb, #PortBHiZ mov loops,#100 Dwait mov loops2,#255 Dwait2 djnz loops2, Dwait2 djnz loops, Dwait mov !rb, #PortBStat setb statusLED mov loops,#100 Dwait3 mov loops2,#255 Dwait4 djnz loops2, Dwait4 djnz loops, Dwait3 mov !rb, #PortBHiZ mov loops,#100 Ewait mov loops2,#255 Ewait2 djnz loops2, Ewait2 djnz loops, Ewait lset 100h ; back to lower half ret ; end debugging code ; ; version notes... ; trying stuff - deleted out chunks to simplify the ; algorithm and letting it control the net more ; (eased up on the critic parts) Controlling a nervous ; net is not straitforward as controlling wheels that ; always go. The algorithm used here cannot sequence ; events so it attempts to find single moves that get ; the job done. Not easy, because the effect of a move ; depends on the amount of bias in the leg when the ; move began. Unfortunately that info is not available ; but somehow in the self adapting tradition it all seems ; to work anyway... actually it's all about impressing ; friends that come over and mess with it, as long as ; it *looks* like it's doing something semi-intelligent ; it matters little what it's actually doing (if I knew:) ; added "look" bit to give some predictive ability (maybe?) ; added check to exit action loop if anything touches