; Filename: CLO.ASM ; ********************************************** ; * Home ball clock * ; * Revision: 1.2 * ; * Date 15/5-98 * ; * Part: 16C84-10 (16R84-10) * ; * Fuses: OSC: HS (10.0 Mhz xtal) * ; * WDT: OFF/ON (C84/F84) * ; * Compiled using MPASM V1.40 * ; ********************************************** ; * Include files: * ; * P16C84.INC * ; ********************************************************************** ; ********************************************************************** list p=16C84 radix dec include "e:\helge\pic\mpasm\p16c84.inc" __FUSES _CP_OFF & _WDT_OFF & _HS_OSC & _PWRTE_ON ERRORLEVEL 1,-302 ; Turn OFF message ID 302 ; ************************************ ; * Port B (RB0-RB7) bit definitions * ; ************************************ MAGNET EQU 1 ; RB1 is the magnet control (active high) MOTOR EQU 2 ; RB2 is the motor control (active high) LED1 EQU 3 ; RB3 is the LED1 output (active low) DET1 EQU 6 ; RB6 is detector input (light->high) BUTTON1 EQU 7 ; RB7 is button (active low input) RBTRIS EQU 0c0h ; RB0-RB5 are outputs RBINIT EQU 000h ; All low (LED1 on) ; ******************************************** ; * Define clock speed and timing parameters * ; ******************************************** ; 10 MHz clock, divided by 4, divided by 256 (prescaler). ; Counter incremented 9765.6 timer per second. ; Counter divides by 256, resulting in 38,15 interrupts per second. MPER100SEC EQU 3815 ; Interrupts per 100 s ; ************************************ ; * Flag variable bits * ; ************************************ NEWMIN EQU 00h ; Set at start of new minute NEWSEC EQU 01h ; Set at start of new second NEWSTIM EQU 02h ; Set at expiry of second timer NEWMTIM EQU 03h ; Set at expiry of millisecond timer TESTMODE EQU 04h ; Testmode flag bit MTESTMODE EQU 10h ; Testmode mask (1 in TESTMODE bit) ; ************************************ ; * Variables * ; ************************************ MSEC EQU 0Ch ; Millisecond counter (1/38 s) SEC EQU 0Dh ; Second counter MIN EQU 0Eh ; Minute counter FLAGS EQU 10h ; Flag bit variable STIM EQU 11h ; Second timer MTIM EQU 12h ; Millisecond timer ; ************************************ ; * Macros * ; ************************************ LED1ON MACRO bcf PORTB,LED1 ENDM LED1OFF MACRO bsf PORTB,LED1 ENDM MOTORON MACRO bsf PORTB,MOTOR ENDM MOTOROFF MACRO bcf PORTB,MOTOR ENDM MAGNETON MACRO bsf PORTB,MAGNET ENDM MAGNETOFF MACRO bcf PORTB,MAGNET ENDM ; ************************************ ; * Reset vector * ; ************************************ org 0x000 ; Reset vector location goto Start ; Begining of Program ; ************************************ ; * Interrupt vector and routine * ; ************************************ org 0x004 ; Interupt vector location IntRoutine clrwdt ; Clear watchdog timer bcf INTCON,T0IF ; Clear T0IF bit decfsz MTIM,F ; If not M-timer expired? goto int1 ; Jump past bsf FLAGS,NEWMTIM ; Set millisecond timer expired bit int1 decfsz MSEC,F ; If not new second return retfie movlw 38 ; 38 ints per second movwf MSEC decfsz STIM,F ; If not new second goto int2 ; Jump past bsf FLAGS,NEWSTIM ; Set second timer expired bit int2 decfsz SEC,F ; If not new minute return retfie movlw 48 ; New minute. 10 extra interrupts movwf MSEC ; every new minute (38+10=48) ; to correct clock movlw 60 movwf SEC bsf FLAGS,NEWMIN ; Set new minute flag decfsz MIN,F ; If not new hour return retfie movlw 28 ; New hour. Fewer interrupts movwf MSEC ; every new hour ; to correct clock movlw 60 movwf MIN retfie ; End of interrupt routine ; ************************************ ; * Main loop * ; ************************************ Start ;******************************** Initialise movlw RBINIT ; Initialise PORTB movwf PORTB bsf STATUS,RP0 ; Switch to bank 1 movlw RBTRIS ; Initialise PORTB direction movwf TRISB movlw 0x87 ; Initialise OPTION reg movwf OPTION_REG bcf STATUS,RP0 ; Switch to bank 0 clrf FLAGS ; Clear all flags movlw 0x01 movwf MIN ; Initialise all counters movwf SEC movwf MSEC movwf STIM movlw 0xA0 ; Initialise interrupt control reg movwf INTCON ;******************************** Is button on already? btfss PORTB,BUTTON1 bsf FLAGS,TESTMODE ; If so set TESTMODE Loop ;******************************** Wait for next minute if not TESTMODE btfsc FLAGS,TESTMODE ; If TESTMODE goto WaitA ; Skip waiting btfss PORTB,BUTTON1 ; If button goto LedBlink1 ; Blink led goto NotLedBlink1 ; Else no blink LedBlink1 btfss MSEC,2 ; If bit 2 of MSEC not set LED1ON NotLedBlink1 btfsc MSEC,2 ; If bit 2 of MSEC set LED1OFF btfss FLAGS,NEWMIN ; If not NEWMIN goto Loop ; Continue waiting for next minute bcf FLAGS,NEWMIN ; Clear new minute flag btfsc MIN,0 ; If even minute goto Loop ; Wait one more minute WaitA ;******************************** Turn on LEDs and wait for button/110s LED1ON movlw 110 ; 110 seconds btfsc FLAGS,TESTMODE ; 5 seconds if testmode movlw 5 movwf STIM ; Set second timer value bcf FLAGS,NEWSTIM ; And clear flag WaitB btfss PORTB,BUTTON1 ; If button press goto MotorOn ; Start motor btfss FLAGS,NEWSTIM ; If timer not expired goto WaitB ; Continue waiting MotorOn ;******************************** LED off, Motor on LED1OFF nop MOTORON movlw (MPER100SEC * 6) / 100 ; 6 seconds movwf MTIM ; Set millisecond timer value bcf FLAGS,NEWMTIM ; And clear flag WaitM1 btfss PORTB,DET1 ; If not light goto WaitM2 btfss FLAGS,NEWMTIM ; If mot millisecond timer expired goto WaitM1 ; Continue waiting WaitM2 btfsc PORTB,DET1 ; If light goto WaitM3 btfss FLAGS,NEWMTIM ; If mot millisecond timer expired goto WaitM2 ; Continue waiting WaitM3 ;******************************** Light detected, wait a bit more movlw (MPER100SEC * 2) / 1000 ; 0.2 seconds movwf MTIM ; Set millisecond timer value bcf FLAGS,NEWMTIM ; And clear flag WaitM4 btfss FLAGS,NEWMTIM ; If timer not expired goto WaitM4 ; Continue waiting Motoff ;******************************** MOTOR OFF MOTOROFF movlw (MPER100SEC * 5) / 1000 ; 0.5 seconds movwf MTIM ; Set millisecond timer value bcf FLAGS,NEWMTIM ; And clear flag WaitC btfss FLAGS,NEWMTIM ; If timer not expired goto WaitC ; Continue waiting ;******************************** MAGNET ON MAGNETON movlw (MPER100SEC * 3) / 1000 ; 0.3 seconds movwf MTIM ; Set millisecond timer value bcf FLAGS,NEWMTIM ; And clear flag WaitD btfss FLAGS,NEWMTIM ; If mot millisecond timer expired goto WaitD ; Continue waiting MAGNETOFF ;******************************** Is button on? btfsc PORTB,BUTTON1 goto Loop movlw MTESTMODE xorwf FLAGS,F ; If so toggle TESTMODE goto Loop ; Continue main loop END