title "Ver13F - Basic Shooting/Polling Software for PIC16F505" #define nDebug ; ; This Program provides a the basis for the OSC/Celestica Sumo Bot ; IR Tag Game. ; ; Ver13F - Modified for PIC16F505/PIC16F630 Code Removed ; ; Ver13 - Put in all the BS2 Interface Commands ; ; Ver12 - Put in BS2 Interface Code ; ; Ver11 - Change Right Side of PIC LED Assignments ; - Point FSR to TRISC for PIC16F630 ; ; Ver10 - Put in 1 Second Delay between Shots ; ; Ver9 - Put in Sense for "Fire"... ; ; Ver8 - Put in "Fire" for 8 cycles of 16 on and off ; ; Ver7 - Move Timer to Mainloop ; - Put in Counter for White LEDs ; - Put in 1 Second Timer for "Hit" ; ; Ver6 - Update for PIC16C505 ; - Update the Timer Operation ; ; Ver5 - Disable RA5/RB5 & RC4 for Vcc/Powered from 100 Ohm Resistor ; - 10-47 uF across IR Receivers ; - Reverse Operation of Left LED ; ; Ver4 - Pins Updated for Actual Device (Should be Final Version) ; - "Spinning" LEDs programmed using TMR0 ; - TMR0 Running with a /256 Prescaler ; ; Ver3 - Poll Left and Right IR Rx'rs and Turn on the "HitLED" when ; their output goes low ; - RC5/RC4/RC3 Changed for Correct Left Rx'r Pinout ; - Right Rx'r Position Incorrect, TBD ; ; Ver2 - Basic Shooting and Polling Software ; - Single Button on Clock Input (RC2) to Initiate Shooting ; - Pull up on Switch on RC2 (This will be basic fire mode) ; - Add Support for PIC16F30 as well as PIC16C505 ; ; Ver1 - Basic I/O Port Setup for the PIC16C505 ; ; ; BS2 Commands ; 1 - Fire (Once Per Second) ; 2 - IR Sensor Off ; 3 - IR Sensor On (Default) ; 4 - White LEDs Off ; 5 - White LEDs ALL ON ; 6 - Left White LED Toggle ; 7 - Right White LED Toggle ; 8 - Rear White LED Toggle ; 9 - White LEDs Cycle (Default) ; 10 - Indicate LED On ; 11 - Indicator LED Off (Default) ; 12 - Hit Counter Clear ; 13 - Maximum Hit Counter 1 (LEDs Flash) ; 14 - Maximum Hit Counter 5 (LEDs Flash) ; 15 - No Maximum Hit (Default) ; 16 - Return Hit Counter ; ; Hardware Notes: ; PIC16C505 running at 4 MHz Using the Internal Clock ; Internal Reset is Used ; RA5/RB5 - Input ; RA4/RB4 - Gnd for Right IR Rx'r ; RA3/RB3 - Negative Active IR Receiver Output (Both RX'rs) ; RA2/RB2 - LED Common Pin ; RA1/RB1 - Data I/O ; RA0/RB0 - Clock Input ; RC5 - Gnd for Left IR Receiver ; RC4 - Input ; RC3 - Left White LED ; RC2 - Rear White LED ; RC1 - Indicator LED ; RC0 - Right White LED #define _IRRx PORTB, 3 #define LEDCommon PORTB, 2 #define ComData PORTB, 1 #define ComClock PORTB, 0 #define LeftLED PORTC, 3 #define RearLED PORTC, 2 #define HitLED PORTC, 1 #define RightLED PORTC, 0 ; ; ; Myke Predko ; 04.09.30 ; list R=DEC variable VarStart = 0x008 ; Determine the Correct Variable Start include "p16F505.inc" ; Constants TwoSecs EQU 100 OneSec EQU 50 HalfSec EQU 25 ThreeQuarterSec EQU 37 ; Register Usage CBLOCK VarStart ; Start of GP Registers i, j, k BS2Byte ; BS2 Send/Receive Value DlayValue:3 ; Three Bytes Needed for Delay Macro FireInnerCounter, FireOuterCounter, FireDlay PulseCount, RXCount WhiteLEDCount, WhiteLEDActive IRHitCount HitCounter, MaxHits ; Count How Many Times Hit Flag ; Status Bits of Operation VariableEnd ENDC if (VariableEnd > 0x020) error "Too Many Variables Used in Application" endif ; Flag Definitions #define LEDActive Flag, 7 ; Bit 7 Set if LED Spin is Active #define IRSensorDis Flag, 6 ; Bit 6 Set if IR Sensor to be Disabled #define MaxHitActive Flag, 5 ; Flashing Because Maximum Hit PAGE ; Macros Dlay Macro Cycles variable CyclesLeft ; Keep Track of Remaining Cycles variable LargeNum CyclesLeft = Cycles local LongLoop if Cycles > 0x04FFFF00 ; Can't Handle the Anything > 83 Seconds (@ 4 MHz) error "Required Delay is longer than 'Dlay' Macro can support" endif if Cycles > 327681 ; Need Large Loop? LargeNum = CyclesLeft / 327681 movlw LargeNum movwf DlayValue + 2 ; Calculate Number of Loops LongLoop: ; Repeat for Each Loop clrf DlayValue + 1 ; Do Maximum Possible Loop Count clrf DlayValue decf DlayValue, f btfsc STATUS, Z decfsz DlayValue + 1, f goto $ - 3 decfsz DlayValue + 2, f ; Repeat Loop goto LongLoop CyclesLeft = CyclesLeft - ((LargeNum * 327681) + 1 + (LargeNum * 3)) endif ; Need Large Loop if Cycles > 14 ; Will a Loop be required? movlw high (((CyclesLeft - 3) / 5) + 256) movwf DlayValue + 1 movlw low (((CyclesLeft - 3)/ 5) + 256) movwf DlayValue decf DlayValue, f ; 5 Cycle Constant Delay Loop btfsc STATUS, Z decfsz DlayValue + 1, f goto $ - 3 CyclesLeft = CyclesLeft - (3 + (5 * ((CyclesLeft - 3)/ 5))) endif ; Finished with Loop Code while CyclesLeft >= 2 ; Put in 2 Instruction Cycle Delays goto $ + 1 CyclesLeft = CyclesLeft - 2 endw if CyclesLeft == 1 ; Put in the Last Required Cycle nop endif endm PAGE __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC_RB4EN PAGE ; Mainline of OSC IR Tag Code org 0 movwf OSCCAL ; Save Calibrated Oscillator Value movlw B'10010111' ; Enable Internal Pull Ups and option ; T0 on Instruction Clock, /256 Prescaler movlw B'00000000' ; RB5 - Input for IR Power ; RB4 - Gnd for Right IR Rx'r ; RB3 - IR Receivers' Vout, Input ; RB2 - LED Common Pin ; RB1 - BS2 Data ; RB0 - BS2 Clock movwf PORTB movlw B'00000000' ; RC5 - Gnd for Left IR Rx'r ; RC4 - Input for IR Power ; RC3 - Positive Active Left White LED ; RC2 - Rear LED ; RC1 - Hit LED ; RC0 - Right LED movwf PORTC movlw B'00101011' ; RB5 - Input for IR Power ; RB4 - Gnd for Right IR Rx'r ; RB3 - Input, IR Receivers' Vout ; RB2 - LED Common Pin ; RB1 - BS2 Data ; RB0 - BS2 Clock tris PORTB movlw B'00010000' ; RC5 - Gnd for Left IR Rx'r ; RC4 - Input for IR Power ; RC3 - Positive Active Left White LED ; RC2 - Rear LED ; RC1 - Hit LED ; RC0 - Right LED tris PORTC ; General Program Initializations clrf IRHitCount clrf Flag bsf LEDActive ; Note LED Can Spin clrf FireDlay clrf HitCounter clrf MaxHits ; Indicate No Maximum Hits movlw 1 ; Indicate which LED is Active movwf WhiteLEDActive movlw 10 ; Loop 10x for LED Display for 1/3 s movwf WhiteLEDCount movlw B'00000001' ; Direct Write to PORTC movwf PORTC ; For Right LED ; Loop Waiting for Button/Polling IR Rx'rs Loop: btfss ComClock ; Read BS2 For Command goto BS2Read btfsc IRSensorDis ; IR Sensors Disabled? goto IRSensorSkip ; Set - Skip btfss _IRRx ; IR Inputs Low? goto IRHit ; Yes, Check Format of Hit Packet IRSensorSkip: btfss TMR0, 7 ; TMR0 > 0x07F? goto Loop bcf TMR0, 7 ; Reset the Counter movf FireDlay, f ; Fire Delay Active? btfss STATUS, Z decf FireDlay, f movf IRHitCount, f ; HIT LED Active? btfss STATUS, Z goto IRHitDecrement decfsz WhiteLEDCount, f ; Decrement the White LED Display goto Loop ; Not Looped 10x movlw 10 movwf WhiteLEDCount ; Reset the Counter btfss MaxHitActive ; If Max Hit, Flash the LEDs goto DoCycle movlw B'00001101' ; Toggle the White LEDs xorwf PORTC, f goto Loop DoCycle: btfss LEDActive ; Can LEDs be Displayed? goto Loop decf WhiteLEDActive, w ; White LED Active? btfss STATUS, Z goto RearActive movlw B'11111110' ; Right LED Off andwf PORTC, w iorlw B'00000100' ; Rear LED On movwf PORTC incf WhiteLEDActive, f ; Indicate Next LED Active goto Loop RearActive: movlw 2 subwf WhiteLEDActive, w btfss STATUS, Z goto LeftActive movlw B'11111011' ; Rear LED Off andwf PORTC, w iorlw B'00001000' ; Rear LED On movwf PORTC incf WhiteLEDActive, f ; Indicate Next LED Active goto Loop LeftActive: movlw B'11110111' ; Rear LED Off andwf PORTC, w iorlw B'00000001' ; Left Off/Right LED Active movwf PORTC ; For Right LED movlw 1 ; Indicate which LED is Active movwf WhiteLEDActive goto Loop IRHitDecrement: ; Turn Off Indicator LED after 1 Second decfsz IRHitCount, f goto Loop bcf HitLED ; Turn LED Off after 1 Second goto Loop IRHit: ; IR Code Received clrf PulseCount ; Keep Track of the Number of Pulses clrf RXCount ; Keep Track of the Length of Pulse IRRXLoop: btfsc _IRRx ; Receive Still Low? goto IRRXLowCheck movlw 1 addwf RXCount, f ; Overflow? goto $ + 1 ; 9 us loop timing btfss STATUS, C goto IRRXLoop IRRXError: ; Invalid signal (> 2295 us) goto Loop IRRXLowCheck: ; Check for Valid Low Period movlw 194 ; Between 1746 and 2295 us subwf RXCount, w btfss STATUS, C goto IRRXError ; Less than 1750 us incf PulseCount, f ; Increment Number of Pulses Received movlw 5 subwf PulseCount, w ; == 5? btfsc STATUS, Z goto IRValidHit ; Yes, Valid Hit clrf RXCount ; Repeat for High IRNXLoop: btfss _IRRx ; Receive Still High? goto IRRXHighCheck movlw 1 addwf RXCount, f ; Overflow? goto $ + 1 ; 9 us loop timing btfss STATUS, C goto IRNXLoop goto IRRXError IRRXHighCheck: ; Check for High Between 1746 and 2295 us movlw 194 subwf RXCount, w btfss STATUS, C goto IRRXError clrf RXCount ; Reset Loop Counter goto IRRXLoop ; See How Long Low IRValidHit: ; Value Hit movlw 20 ; Indicate Hit LED on for 2/3 Second addwf IRHitCount, f movlw B'00000010' ; Just Turn on the Indicator LED iorwf PORTC, f btfsc MaxHitActive goto Loop ; Maximum Hits Already Flashing, Return incf HitCounter, f ; Increment the Number of Hits movf MaxHits, w ; Infinite Number of Maxium Hits? btfsc STATUS, Z goto Loop ; Yes, Just Return subwf HitCounter, w ; Maximum Number of Hits? btfss STATUS, Z goto Loop bsf MaxHitActive ; Yes, Start Flashing movlw B'00001101' ; Turn on All the LEDs iorwf PORTC, f goto Loop ; Loop Forever BS2Read: ; Decode the BS2 Command movlw 8 ; Count Number of Bits to Read movwf i movlw 3 ; Wait 3.8 msecs for Data to become active movwf k clrf j BS2RLoop1: ; Wait for Data to become Active btfsc ComClock goto BS2RSkip3 decfsz j, f ; Wait no more than 3 msecs goto BS2RLoop1 btfsc ComClock goto BS2RSkip3 decfsz k, f goto BS2RLoop1 BS2RError: ; Nothing Valid Received movlw B'00101011' ; Return PORTA/B to Original State tris PORTB goto Loop ; Return BS2RSkip3: ; Clock High, Wait for it to go low movlw 4 movwf j BS2RLoop3: ; Wait no more than 15 msecs for Clock Pulse Active btfss ComClock goto BS2RSkip4 decfsz j, f goto BS2RLoop3 goto BS2RError BS2RSkip4: ; Clock Low/Read the Data Bit bcf STATUS, C btfsc ComData bsf STATUS, C rrf BS2Byte, f ; Shift in the Bit decfsz i, w ; At the Last Bit? goto BS2RSkip2 ; - No... movlw 16 ; Return Hit Count? subwf BS2Byte, w btfsc STATUS, C goto BS2RSkip5 ; Yes, No Final Clock High BS2RSkip2: ; Clock Still Low movlw 100 movwf j BS2RLoop2: ; Wait no more than 500 usecs for Clock High btfsc ComClock goto BS2RSkip5 decfsz j, f goto BS2RLoop2 goto BS2RError BS2RSkip5: ; Clock High Again/Finished with the Bit decfsz i, f ; Read Another Bit? goto BS2RSkip3 movlw 17 ; Invalid Command? subwf BS2Byte, w btfsc STATUS, C goto BS2RError ; > 11 is Invalid movlw 16 ; Look for Basic/No Return Data Commands subwf BS2Byte, w btfss STATUS, C goto BS2PrimaryCommand ; Return the Number of Times Hit movf HitCounter, w ; Return the Number of Times hit movwf BS2Byte movlw B'00101001' ; PORTA/B Driving Out Data tris PORTB movlw 8 ; Count Number of Bits to Send Out movwf i movlw 2 ; Wait to Reply no more than 2.5 msecs movwf k clrf j BS2RLoop4: ; Wait for Data to become Active btfsc ComClock goto BS2RSkip6 decfsz j, f ; Wait no more than 3 msecs goto BS2RLoop4 decfsz k, f goto BS2RLoop4 goto BS2RError BS2RSkip6: ; Output the Data Bit rrf BS2Byte, f ; Put the LS Data Bit into Carry movf PORTB, w iorlw 1 << 1 ; Bit 1 is the Data Bit btfss STATUS, C andlw 0x03F ^ (1 << 1) ; If Carry Reset, Reset movwf PORTB movlw 4 movwf j BS2RLoop5: ; Wait no more than 15 msecs for Clock Pulse Active btfss ComClock goto BS2RSkip7 decfsz j, f goto BS2RLoop5 goto BS2RError BS2RSkip7: ; Wait for Line Low to End movlw 200 movwf j BS2RLoop6: ; Wait no more than 1 msec for Clock High btfsc ComClock goto BS2RSkip8 decfsz j, f goto BS2RLoop6 goto BS2RError BS2RSkip8: ; More Bits to Send? decfsz i, f goto BS2RSkip6 ; Yes, Loop Around Again goto BS2RError ; Finished, Return and Keep Processing BS2PrimaryCommand ; Change the Command Operation movf BS2Byte, w ; Get the New Command xorlw 1 ; Fire? btfsc STATUS, Z goto Fire xorlw 2 ^ 1 ; Turn off IR Sensors? btfsc STATUS, Z bsf IRSensorDis ; Yes, Disable the Sensor xorlw 3 ^ 2 ; Turn on the IR Sensors? btfsc STATUS, Z bcf IRSensorDis xorlw 4 ^ 3 ; White LEDs Off btfsc STATUS, Z goto WhiteLEDsOff xorlw 5 ^ 4 ; ALL White LEDs On btfsc STATUS, Z goto WhiteLEDsON xorlw 6 ^ 5 ; Just Left White LED Toggle btfsc STATUS, Z goto WhiteLeftLEDToggle xorlw 7 ^ 6 ; Just Right White LED Toggle btfsc STATUS, Z goto WhiteRightLEDToggle xorlw 8 ^ 7 ; Just Rear White LED Toggle btfsc STATUS, Z goto WhiteRearLEDToggle xorlw 9 ^ 8 ; White LEDs Flash in Sequence (Default) btfsc STATUS, Z goto WhiteLEDsCycle xorlw 10 ^ 9 ; IR Hit LED On btfsc STATUS, Z bsf HitLED xorlw 11 ^ 10 ; IR Hit LED Off (Default) btfsc STATUS, Z bcf HitLED xorlw 12 ^ 11 ; Clear Hit Counter btfsc STATUS, Z goto HitClear xorlw 13 ^ 12 ; Maximum of 1 Hit btfsc STATUS, Z goto Max1Hit xorlw 14 ^ 13 ; Maximum of 5 Hits btfsc STATUS, Z goto Max5Hits xorlw 15 ^ 14 ; No Maximum Number of Hits btfsc STATUS, Z goto NoMaxHits goto BS2RError ; Otherwise, Unknown/Completed Command - Return HitClear: ; Clear the Number of Hits clrf HitCounter bcf MaxHitActive ; Turn Off Flashing Hit Counter goto WhiteLEDsCycle Max1Hit: ; Maximum 1 Hit movlw 1 goto MaxHitFinish Max5Hits: ; Maximum 5 Hits movlw 5 goto MaxHitFinish NoMaxHits: ; No Maximum Hits movlw 0 MaxHitFinish: movwf MaxHits bcf MaxHitActive ; Turn Off Flashing Hit Counter clrf HitCounter goto BS2RError WhiteLEDsCycle: ; Resume Cycling the LEDs movlw B'11110010' ; Turn on White LEDs andwf PORTC, f movlw B'00000001' ; Turn on White LEDs iorwf PORTC, f bsf LEDActive goto BS2RError WhiteLEDsOff: ; Turn off all the White LEDs movlw B'11110010' ; Turn on White LEDs andwf PORTC, f goto WhiteLEDState WhiteLEDsON: ; Turn on ALL White LEDs movlw B'00001101' ; Turn on ALL White LEDs iorwf PORTC, f goto WhiteLEDState WhiteLeftLEDToggle: ; Toggle Leftt LED ONLY movlw 8 ; Left on PORTC, 3 xorwf PORTC, f goto WhiteLEDState WhiteRightLEDToggle: ; Toggle Right LED ONLY movlw 1 ; Right on PORTC, 0 xorwf PORTC, f goto WhiteLEDState WhiteRearLEDToggle: ; Toggle Rear LED ONLY movlw 4 ; Rear on PORTC, 2 xorwf PORTC, f WhiteLEDState: ; Put the White LEDs into a Specific State bcf LEDActive ; Turn Off LED Cycling goto BS2RError Fire: ; "Fire" the Cannon movf FireDlay, f ; Can Fire Take Place? btfss STATUS, Z goto BS2RError movlw 15 ; Eight "Fire" Cycles movwf FireOuterCounter FireLoop: btfss FireOuterCounter, 0 ; Odd? goto FireBlank movlw 157 ; 26 us period 79x movwf FireInnerCounter FireOutLoop: btfss FireInnerCounter, 0 ; Low/High? goto FireLow bsf LEDCommon ; IRLED High Dlay 12 bcf LEDCommon ; High for 13 Cycles nop ; Time Low to 13 Cycles FireLow: ; Nothing Happening/Just Skip Over FireOutCheck: decfsz FireInnerCounter, f goto FireOutLoop goto FireLoopDone FireBlank: Dlay 2044 ; Off for same amount of time FireLoopDone: decfsz FireOuterCounter, f goto FireLoop movlw 30 ; Delay Next Shot for a Second movwf FireDlay goto BS2RError if ($ >= 512) error "Program Too Large for PIC16C505" endif end