;******************************** ; written by:John Morton * ; date:25/08/97 * ; version:1.0 * ; file saved as:RanLott * ; for PIC71 * ; clock frequency:2.47 MHz * ;******************************** ; PROGRAM FUNCTION:A multipurpose random number generator with ; various modes including a lottery number function. list P=16C71 include Òc:\pic\p16c71.incÓ ;============ ; Declarations: porta equ 05 portb equ 06 dig1 equ 0C dig2 equ 0D dig3 equ 0E dig4 equ 0F Chooser equ 10 ChaseCount equ 11 Skin equ 12 Random equ 13 Mark240 equ 14 LetGoCount equ 15 TouchTime equ 16 General equ 17 Scaler equ 18 LottCount equ 19 Tens equ 1A ADCount equ 20 Post28 equ 21 Post70 equ 22 Lott1 equ 1B Lott2 equ 1C Lott3 equ 1D Lott4 equ 1E Lott5 equ 1F #define sec3 General, 0 org 0 goto Start ;=========== ; Subroutines: Init clrf porta ; resets I/O ports clrf portb b Init+4 ; leaves address 0004 for isr b isr movlw 23 ; clears file register from number 23 to movwf FSR ; the FSR ClearLoop decf FSR ; clrf INDF ; movfw FSR ; btfsc STATUS,Z ; goto ClearLoop ; bsf STATUS,5 ; selects bank 1 movlw bÕ00001Õ ; RA0:contacts,RA1-RA4:seven movwf TRISA ; segment controlling pins movlw bÕ00000001Õ ; RB0:mode button,RB1-RB7: movwf TRISB ; seven segment code movlw bÕ00000111Õ ; sets up TMR0,prescaled at 256 movwf OPTION_REG ; movlw bÕ00000010Õ ; RA0 and RA1 are analogue,Vref is movwf ADCON1 ; supply voltage bcf STATUS,5 ; returns to bank 0 movlw bÕ00110000Õ ; sets up interrupts:TMR0 on movwf INTCON ; external on,global off movlw bÕ01000001Õ ; sets up A/D conversion: movwf ADCON0 ; clock:Fosc/8,channel:AN0,converter is on movlw dÕ4Õ ; so that device starts up in 1-6 mode movwf Chooser ; movlw dÕ28Õ ; sets up postscalers movwf Post28 ; movlw dÕ70Õ ; movwf Post70 ; return ; returns from subroutine isr btfss INTCON,1 ; has external interrupt occurred? b TMRInt ; no, so goes to timer interrupt ; yes, so continues incf Chooser ; goes on to next mode movlw dÕ5Õ ; has it gone through all five modes? subwf Chooser,w ; btfsc STATUS,Z ; clrf Chooser ; yes,so reset back to mode 1 (1-6) movfw Chooser ; takes the number out of Chooser addwf PCL,f ; skips that many instructions b Dis6 ; 1-6_ b DisLot ; Lott b Dis12 ; 1-12 b Dis99 ; 1-99 b Dis66 ; -6-6 Dis6 movlw bÕ10111110Õ ; 6 movwf dig3 movlw bÕ00000000Õ ; blank movwf dig4 b DisCommon ; goes to common place to set up 1 - Dis12 movlw bÕ11011010Õ ; 2 movwf dig4 movlw bÕ01100000Õ ; 1 movwf dig3 b DisCommon ; 1- Dis99 movlw bÕ11100110Õ ; 9 movwf dig3 movlw bÕ11100110Õ ; 9 movwf dig4 b DisCommon ; 1- DisCommon movlw bÕ01100000Õ ; 1 movwf dig1 movlw bÕ00000010Õ ; - movwf dig2 return ; returns,without re-enabling the interrupts DisLot movlw bÕ00011100Õ ; L movwf dig1 movlw bÕ00111010Õ ; o movwf dig2 movlw bÕ00001110Õ ; t movwf dig3 movlw bÕ00001110Õ ; t movwf dig4 return Dis66 movlw bÕ00000010Õ ; sets a dash movwf dig1 movwf dig3 movlw bÕ10111110Õ ; sets a number 6 movwf dig2 movwf dig4 return TMRInt bsf INTCON,4 ; enables external interrupt decfsz Post28 ; first postscaled by 28 retfie ; movlw dÕ28Õ ; yes,so resets first postscaler movwf Post28 ; bcf sec3 decfsz Post70 ; secondly postscaled by 70,(3.5 minutes passed?) retfie ; no movlw dÕ70Õ ; yes,so resets second postscaler movwf Post70 ; clrf portb ; clears outputs clrf porta ; sleep ; sleeps (low power mode) retfie ; returns,enabling the global interrupt display movfw TMR0 ; use TMR0 to select one of four sections andlw bÕ00000011Õ ; addwf PCL ; b digit1 b digit2 b digit3 b digit4 digit1 movlw bÕ10000Õ ; turns on relevant display movwf porta ; movfw dig1 movwf portb ; moves relevant code into port b retfie digit2 movlw bÕ00010Õ ; turns on relevant display movwf porta ; movfw dig2 movwf portb ; moves relevant code into port b retfie digit3 movlw bÕ00100Õ ; turns on relevant display movwf porta ; movfw dig3 movwf portb ; moves relevant code into port b retfie digit4 movlw bÕ01000Õ ; turns on relevant display movwf porta ; movfw dig4 movwf portb ; moves relevant code into port b retfie Chaser movfw Mark240 ; has a tenth of a second passed? subwf TMR0,w ; btfss STATUS,Z ; return ; no,so returns movlw dÕ240Õ ; yes,so continues and resets marker addwf Mark240 ; incf ChaseCount ; scrolls through the 3 different display movfw ChaseCount ; codes,creating a chase addwf PCL b Chase1 b Chase2 b Chase3 ; MessageChooser movlw dÕ12Õ ; is Skin between 11 and 12? subwf Skin,w ; btfss STATUS,C ; b sad ; yes,so displays SAd movlw dÕ15Õ ; is Skin between 13 and 15? subwf Skin,w ; btfss STATUS,C ; b bad ; yes,so displays bAd movlw dÕ20Õ ; is Skin between 16 and 20? subwf Skin,w ; btfss STATUS,C ; b cool ; yes,so displays cool movlw dÕ25Õ ; is Skin between 21 and 25? subwf Skin,w ; btfss STATUS,C ; b john ; yes,so displays John movlw dÕ35Õ ; is Skin between 26 and 35? subwf Skin,w ; btfss STATUS,C ; b hot ; yes,so displays hot movlw dÕ50Õ ; is Skin between 36 and 50? subwf Skin,w ; btfss STATUS,C ; b tops ; yes,so displays toPS b ace ; no,so displays ACE (above 50) Decoder addwf PCL ; converts number into 7 seg.code retlw bÕ11111100Õ ; number 0 retlw bÕ01100000Õ ; number 1 retlw bÕ11011010Õ ; number 2 retlw bÕ11110010Õ ; etc. retlw bÕ01100110Õ ; retlw bÕ10110110Õ ; retlw bÕ10111110Õ ; retlw bÕ11100000Õ ; retlw bÕ11111110Õ ; retlw bÕ11100110Õ ; ; Changer movfw Skin ; gets new random number addwf Random ; b RanLot ; converts it to a number between 1 and 49 ; ======================= ; Program Start: Start call Init ; set everything up bsf INTCON,1 ; tell the isr to go to mode changing section call isr ; call isr Main bsf ADCON0,2 ; starts A/D conversion call display ; sorts out displays btfsc portb,0 ; tests for up button b ADTest ; still pressed,so changes nothing movlw bÕ10100000Õ ; released,so enables TMR0 and global movwf INTCON ; interrupt ADTest btfsc ADCON0,2 ; conversion is in progress b Main+1 ; goes back to main,and skips one line movlw dÕ10Õ ; is result less than 10? (are contacts subwf ADRES,w ; pressed?) btfss STATUS,C ; b Main ; no,so loops back movlw dÕ28Õ ; resets timing registers movwf Post28 ; movlw dÕ70Õ ; movwf Post70 ; bcf INTCON,7 ; no more interrupts from now on Stabilizer bsf ADCON0,2 ; starts conversion btfsc ADCON0,2 ; has it finished? b Stabilizer ; no,so keeps looping decfsz ADCount ; has this happened 256 times b Stabilizer ; no,so loops back movfw ADRES ; yes,so stores A/D result movwf Skin Main2 bsf ADCON0,2 ; starts A/D conversion (are contacts released?) call Chaser ; sorts out chasing while contacts are pressed call display ; btfsc ADCON0,2 ; is conversion finished? b Main2+1 ; no,so loops back movlw dÕ10Õ ; is A/D low enough to suggest finger subwf ADRES,w ; has been removed? btfsc STATUS,C ; b Main2 ; no,so loops back and starts another conversion decfsz LetGoCount ; yes,confirms low result 200 times b Main2 ; movlw dÕ200Õ ; resets the counting GPF register movfw LetGoCount ; movfw TMR0 ; takes the number out of TMR0 movwf TouchTime ; stores it in TouchTime call MessageChooser ; choose message using number in Skin movlw dÕ28Õ ; resets first postscaler,so that the PIC movwf Post28 ; times the full 3 seconds bsf sec3 ; Loop3Sec movlw bÕ10100000Õ ; enables TMR interrupt movwf INTCON ; call display ; keeps displays going btfsc sec3 ; b Loop3Sec ; keeps looping until 3 seconds have passed movfw TouchTime ; adds TouchTime and Skin together, addwf Skin,w ; storing the result in the GPF,random movwf Random ; movfw Chooser ; use the mode to jump to the correct addwf PCL ; section b Ran6 b RanLot b Ran12 b Ran99 b Ran6 ; to begin with,it is the same as 1-6 mode Ran6 movlw dÕ6Õ b Adder Ran12 movlw dÕ12Õ b Adder Ran99 movlw dÕ99Õ b Adder Adder movwf Scaler ; stores the number from Ran6,Ran12,or Ran99 movfw Scaler ; repeatedly adds the number until it addwf Random ; passes 255 btfss STATUS,C ; is the value suitable? b Adder+1 ; no,so loops back incf Random ; adds one to Random btfss Chooser,2 ; -6-6 mode? b TensLoop+1 ; no,so carries on movwf Random ; movwf Tens ; stores as first 1-6 value addwf TouchTime ; gets new random number movwf Random ; Ran66 movlw dÕ6Õ ; converts it into 1-6 addwf Random ; btfss STATUS,C ; b Ran66 ; incf Random,w ; b Continue66 ; jumps to correct place in TensLoop RanLot movlw dÕ49Õ ; repeatedly adds 49 until it goes past addwf Random ; 255 btfss STATUS,C ; is number suitable? b RanLot ; no,so loops back incf Random ; adds on,so it is between 1 and 49 CompareLott movlw 1Bh ; selects Lott1 first movwf FSR movfw INDF ; compares with previous lottery values subwf Random,w ; btfsc STATUS,Z ; b Changer ; the two are the same,so gets new number incf FSR ; moves on to next lottery number btfss FSR,5 ; has it gone too far? b CompareLott+2 ; no,so loops back ; yes,so continues movfw LottCount ; use number from LottCount,and add addlw 1B ; 1B to it in order to select the correct GPF. movwf FSR ; movfw Random ; movwf INDF ; incf LottCount ; moves on to next lottery number TensLoop incf Tens ; works the tens digit of the number movlw dÕ10Õ ; (keeps subtracting 10 until result is subwf Random ; negative) btfsc STATUS,C ; b TensLoop ; movlw dÕ10Õ ; gets units value by adding 10 to addwf Random,w ; Random and leaving the result in the working register Continue66 call Decoder ; converts units value into 7 seg.code movwf dig4 ; moves code into appropriate digit clrf dig3 ; blanks out left three digits clrf dig2 ; clrf dig1 ; movfw Tens btfsc STATUS,Z ; checks to see if tens is zero b LottCounter ; yes,so displays nothing on dig3 call Decoder ; converts result into 7 seg code btfss Chooser,2 ; is the device in -6-6 mode? b Not66 ; goes to a place where the tens is shown on dig3 movwf dig1 ; in -6-6 mode,so moves code into dig1 b LottCounter ; now goes to label the lottery number correctly Not66 movwf dig3 ; moves code into dig 3 LottCounter clrf Tens ; resets Tens register decfsz Chooser,w ; is the device in lottery mode? b Main ; no,so loops back to main ; yes,so continues movlw bÕ00000010Õ ; displays a dash on digit 2 movwf dig2 ; movfw LottCount ; takes the number out of LottCount call Decoder ; and uses it in dig1 movwf dig1 ; movlw dÕ6Õ ; has LottCount gone too far? subwf LottCount,w ; btfss STATUS,Z ; goto Main ; clrf LottCount ; yes,so resets it clrf Lott1 ; clrf Lott2 ; clrf Lott3 ; clrf Lott4 ; clrf Lott5 ; goto Main ; loops back to the beginning ; sad call _S movwf dig1 call _A movwf dig2 call _d movwf dig3 call blank movwf dig4 return bad call _b movwf dig1 call _A movwf dig2 call _d movwf dig3 call blank movwf dig4 return cool call _C movwf dig1 call _O movwf dig2 call _O movwf dig3 call _L movwf dig4 return john call _j movwf dig1 call _o movwf dig2 call _h movwf dig3 call _n movwf dig4 return hot call _h movwf dig1 call _o movwf dig2 call _t movwf dig3 call blank movwf dig4 return tops call _t movwf dig1 call _o movwf dig2 call _P movwf dig3 call _S movwf dig4 return ace call _A movwf dig1 call _C movwf dig2 call _E movwf dig3 call blank movwf dig4 return _A retlw bÕ11101110Õ ; letter A _b retlw bÕ00111110Õ ; letter b _C retlw bÕ10011100Õ ; letter C _c retlw bÕ00011010Õ ; letter c _d retlw bÕ01111010Õ ; letter d _E retlw bÕ10011110Õ ; E _F retlw bÕ10001110Õ ; F _g retlw bÕ11110110Õ ; g _H retlw bÕ01101110Õ ; H _h retlw bÕ00101110Õ ; h _I retlw bÕ00001100Õ ; I _i retlw bÕ00001000Õ ; i _j retlw bÕ01110000Õ ; j _L retlw bÕ00011100Õ ; L _n retlw bÕ00101010Õ ; n _O retlw bÕ11111100Õ ; O _o retlw bÕ00111010Õ ; o _P retlw bÕ11001110Õ ; P _q retlw bÕ11100110Õ ; q _r retlw bÕ00001010Õ ; r _S retlw bÕ10110110Õ ; S _t retlw bÕ00001110Õ ; t _U retlw bÕ01111100Õ ; U _u retlw bÕ00111000Õ ; u _y retlw bÕ01110110Õ ; y blank retlw bÕ00000000Õ ; blank Chase1 movlw bÕ00000100Õ ; sets up first chase pattern movwf dig1 ; movlw bÕ00010000Õ movwf dig2 movlw bÕ10000000Õ movwf dig3 movlw bÕ00100000Õ movwf dig4 return Chase2 movlw bÕ10010000Õ ; sets up second chase pattern movwf dig1 ; movlw bÕ00000000Õ movwf dig2 movlw bÕ00000000Õ movwf dig3 movlw bÕ10010000Õ movwf dig4 return Chase3 movlw bÕ00001000Õ ; sets up third chase pattern movwf dig1 ; movlw bÕ10000000Õ movwf dig2 movlw bÕ00010000Õ movwf dig3 movlw bÕ01000000Õ movwf dig4 movlw dÕ255Õ ; resets ChaseCount GPF register movwf ChaseCount ; return END