	PROCESSOR 12F675
	TITLE  ENIGMA.ASM
	__CONFIG H'004C'	;xx00-0000-0100-1100
;;;;	__CONFIG H'004D'   ;;;;TEST PUTS CLOCK OUT
	; OSCILLATOR INTERNAL, NO OUTPUT CLOCK
	; WATCHDOG TIMER ON
	; POWER-UP TIMER ON
	; PROGEAM EE PROTECT ON
	; MASTER CLEAR ENABLE  I/O PIN
	; DATA EE READ PROTECT ON
	; BROWN OUT DETECT	ON
	; INTERNAL OSCILLATOR, NO OUTPUT
;
;_______________________________________________________________________________
;
;	COPYRIGHT  2004
;	THE PAK ENGINEERS
;	3985 TONAWANDA CREEK ROAD
;	EAST AMHERST, NY 14051
;
;_________________________________________________________________________________
;
;  PROGRAM DESCRIPTION
;	THE PROGRAM GENERATES 100 US PULSES WITH RATE FROM AB0UT 6 HZ TO 256 HZ DEPENDING
;	ON THE VOLTAGE ON PIN 3.  IT ALSO MONITORS THE POWER SUPPLY VIA PIN 7.  IF THE VOLTAGE 
;	IS TOO HIGH OR LOW, NO PULSES ARE GENERATED AND THE LED CONNECTED TO PIN 6 BLINKS.  
;	IT BLINKS AT 1 HZ IF THE VOLTAGE IS LOW AND AT 5 HZ IF IT'S TOO HIGH.  NORMAL OPERATION
;	IS SIGNIFIED WITH A STEADY LIGHT.  A SPECIAL FUNCTION OF THE LED IS THAT IT IS USED 
;	AS A VOLTAGE REFERENCE.  THE VOLTAGE ACROSS THE LES IS MEASURED VIA PIN 5.  IF IT 
;	APPEARS TO RISE THEN IT MEANS THAT THE ACTUAL VCC/REFERENCE IS DROPPING AND THE 5 VOLT
;	REGULATOR (78L05) ISN'T REGULATING.
;
;_______________________________________________________________________________________
;
;		REGISTER NAMES AND ASSIGNMENTS
;
PCL 	EQU 	02H;  PROGRAM COUNTER REGISTER
STATUS 	EQU		03H;  STATUS REGISTER
ADHIGH	EQU		01EH; 8 MSB'S OF A/D READING
ADLOW	EQU		09EH; 2 LSB'S OF A/D READING  (NOT USED)
ADSEL	EQU		01FH; A/D CONTROL REGISTER/CHANNEL SELECT
ADSET	EQU		09FH; A/D SET-UP REGISTER
INTCTL	EQU		0BH;  MAIN INTERRUPT CONTROL PORT
OPTIN	EQU		081H; OPTION REGISTER
WKPUP	EQU		095H; WEAK PULL-UP REGISTER
OSCAL	EQU		090H; OSCILLATOR CALIBRATION ADJUSTMENT REGISTER
;
;	PORT NAMES AND PIN ASSIGNMENTS
;
PORTA	EQU		05H;  I/O PORT  (ONLY ONE FOR THIS CHIP)  ONLY 6 BITS AVAILABLE
	;	BIT 0 = PIN 7 = GPIO-0	USED AS ANALOG INPUT TO MONITOR VCC
	;	BIT 1 =	PIN 6 = GPIO-1	USED AS DIGITAL OUTPUT TO DRIVE LED
	;	BIT 2 = PIN 5 =	GPIO-2	USED AS ANALOG INPUT TO MONITOR LED VOLTAGE
	;	BIT 3 = PIN 4 =	GPIO-3	NOT USED/NOT CONNECTED PROGRAM AS INPUT 
	;	BIT 4 = PIN 3 =	GPIO-4	USED AS AN ANALOG INPUT TO MONITOR PULSE RATE CONTROL
	;	BIT 5 = PIN 2 =	GPIO-5	USED AS A DIGITAL OUTPUT FOR OUTPUT PULSES
	;				NOTE PIN 1 = VCC AND PIN 8 = GND
;
;	CONSTANT NAMES
LOOPCNT	EQU	017H;  LOOP COUNTER CONSTANT VALUE FOR 100 US DELAY LOOP
;
;	REGISTER FILE NAMES
LPCT	EQU	020H;   GP REGISTER FOR 100 US DELAY
ADSAVE	EQU 021H;	SAVE A/D READING HERE--ONLY 8 MSB USED
DLY		EQU 022H;	0-32 VALUE REPRESENTING 0.004 SECONDS PER BIT  
DLY4MS	EQU 023H;	USED FOR 4 MS DELAY LOOP
DLYXMS	EQU	024H;	USED FOR RATE PERIOD DELAY LOOP
;
;____________________________________________________________________________________
;
	ORG 10H; SKIP OVER INTERRUPT VECTOR JUST TO BE SAFE 
SETUP;		SET UP I/O PINS, A/D REGISTERS, WATCHDOG
	CLRWDT;  GIVES 18 MS FOR SET-UP
	CLRF PORTA; BE SURE OUTPUTS ARE LOW
	BSF STATUS, 5; POINT TO SECOND PAGE ******************************************************
	CLRF OPTIN; ENABLE PULL-UPS, NO WDT PRESCALER (TIMEOUT=18 mS), OTHERS DONT CARE
	CLRF WKPUP; TURN OFF INDIVIDUAL PULL-UPS...NONE ARE USED...NO DIGITAL INPUTS
	CLRF INTCTL;  NO INTERUPTS USED  (SAME FILE ON FIRST PAGE)
; NOW SET-UP I/O PINS:  2,6 DIGITAL OUTPUT, 3,5,7 ANALOG IN, 4 DIGITAL INPUT 
	MOVLW B'00011101';  ONLY DIGITAL OUTPUTS ARE GPIO-1 AND GPIO-5
	MOVWF PORTA;  LOAD THE TRIS VALUE (SUB-PAGE ADDRESSES ARE THE SAME)
; SET UP A/D CONVERTER
	MOVLW B'01011101';  ANALOG INPUT ON GP0, GP2, GP4 OR PINS 7, 5, 3.   A/D CLK=FOSC/16 
	MOVWF ADSET;  
; SET-UP MAIN OSCILLATOR CALIBRATION
	CALL H'03FF';  GETS CALIBRATION VALUE FROM OUTSIDE NORMAL MEMORY WORKSPACE
	MOVWF OSCAL;  LOAD IT INTO LOCAL MEMORY
	BCF STATUS, 5;  GO BACK TO FIRST PAGE***********************************************************
	CLRF PORTA;  MAKE SURE PORTA OUTPUTS ARE LOW
; MOVE OSCILLATOR CALIBRATION FROM OUTSIDE INTO SPECIAL REGISTER
;	FINALLY DONE SET-UP
;_____________________________________________________________________________________
MAINLOOP;   REAL PROGRAM LOGIC STARTS HERE
;
;
CKPOWER;    POWER S/B ABOVE THE DROP-OUT VOLTAGE OF THE REGULATOR (>7 VOLTS)
;			POWER SHOULD BE LESS THAN TYPICAL 12 VOLT ADAPTER (<18 VOLTS)
;			SINCE RESISTOR NETWORK PROVIDES 1/6 OF INPUT VOLTAGE WE WANT
;			TO SEE 1.2V (=7.2V) TO 3.0V (=18V) VOLTS AT A/D.  
;			WITH 5 VOLT REFERENCE THIS CORRESPONDS TO 61/256 TO 153/256.
	CALL GETVCC;  READ THE VOLTAGE
	MOVLW D'061'; LOWER LIMIT
	SUBWF ADSAVE, 0;  (ADSAV-61)--->W  POSITIVE OR 0 RESULT MEANS POWER IS OK 
	BTFSS STATUS, 0;  IF CARRY IS '1' RESULT IS POSITIVE AND POWER IS OK	
	GOTO SLOWBLINK;  POWER IS TOO LOW HERE
	MOVLW D'153'; HIGHER LIMIT
	SUBWF ADSAVE, 0;  (ADSAV-153)--->W  NEGATIVE RESULT MEANS POWER IS OK
	BTFSC STATUS, 0;  IF CARRY IS '0' RESULT IS NEGATIVE AND POWER IS OK
	GOTO FASTBLINK; POWER IS TOO HIGH HERE
;
CKLED;    IF POWER DROPS TOO FAR THE 5V REGULATOR DOESN'T REGULATE AND THE A/D
;			DOESN'T WORK PROPERLY. IT THINKS THE POWER IS OK.  
;			USE RED LED VOLTAGE AS REFERENCE.  S/B 1.6V TO 1.9V DEPENDING ON LED.
;			SO, IF LED VOLTAGE READS 2.1V OR MORE THEN 5 VOLT SUPPLY IS BAD.
;			THIS CORRESPONDS IS 108/256
;
;	NOTE:  SPECIFIC LEDS PURCHASED HAVE VERY LOW V-DROP OF 1.5V (=76/256)
;			SO CHANGE THRESHOLD TO 90/256 
;
	BSF PORTA, 1;  LED MUST BE ON TO MEASURE VOLTAGE DROP
	CALL GETLED
	BCF PORTA, 1;  TURN OFF LED
	MOVLW D'90';  HIGHEST ALLOWABLE LED VALUE
	SUBWF ADSAVE, 0;   (ADSAV-108)---> W  NEGATIVE RESULT MEANS POWER IS OK
	BTFSC STATUS, 0;  IF CARRY IS '0' RESULT IS NEGATIVE AND POWER IS OK
	GOTO SLOWBLINK;  LED VOLTAGE IS TOO HIGH HERE
;
PULSEIT;  POWER IS OK HERE SO SENT OUT A PULSE AND WAIT ACCORDING TO REPITION RATE


	CALL GETRATE;    GET VOLTAGE FROM POT SETTING.  HIGHER VOLTAGE IS HIGHER RATE.
		;RATE IS FROM 256 HZ TO 7.8 HZ OR 0.0039 SEC AND 0.128 SEC PER PERIOD
		;IF RESOLUTION IS SET TO 0.004 THEN THERE ARE 32 RATES FROM 0.0039 TO 0.128
		;(0.004 X 32 = 0.128).  
;;;;;;;;;;;;	BSF PORTA, 1; TURN ON LED   FOR SOME REASON THIS DOESN'T WORK HERE!
	BSF PORTA, 5; START THE PULSE
	CALL WAIT100US; WAIT FOR 100 uS
	BCF PORTA, 5; END THE PULSE
;	NOW WAIT OUT PERIOD FROM 0.004 SEC TO 0.128 SEC
	MOVFW ADSAVE; 
	MOVWF DLY;  MOVE A/D VALUE TO WORK REGISTER
	RRF DLY, 1;  ONLY 5 LSB'S ARE USED FOR A RATE OF 1 TO 32.
	RRF DLY, 1;  SHIFT MSB'S RIGHT 3 POSITIONS
	RRF DLY, 1;   
	MOVLW H'01F';  THEN STRIP OFF LEFT-MOST 3 BITS TO GIVE 5 BIT RESULT
	ANDWF DLY, 1;  WITH A VALUE OF 0 TO 32.  
	BSF PORTA, 1; TURN ON LED************  BUT IT WORKS HERE!  ***********
	CALL LONGDLY;  WAIT FOR PERIOD DEPENDING ON POT SETTING
	GOTO MAINLOOP;  
;
FASTBLINK;     TURN ON LED FOR 100 MS AND THEN OFF FOR 100 MS
	BSF PORTA, 1; TURN ON LED
	MOVLW D'025';  LONGDLY WRKS IN 4 MS STEPS.  SO 25 LOOPS IS 100 MS
	MOVWF DLY
	CALL LONGDLY
	BCF PORTA, 1; TURN OFF LED
	MOVLW D'025';  LONGDLY WRKS IN 4 MS STEPS.  SO 25 LOOPS IS 100 MS
	MOVWF DLY
	CALL LONGDLY
	GOTO MAINLOOP	
;
SLOWBLINK;		TURN ON LED FOR 500 MS AND THEN OFF FOR 500 MS
	BSF PORTA, 1; TURN ON LED
	MOVLW D'125';  LONGDLY WRKS IN 4 MS STEPS.  SO 125 LOOPS IS 500 MS
	MOVWF DLY
	CALL LONGDLY
	BCF PORTA, 1; TURN OFF LED
	MOVLW D'125';  LONGDLY WRKS IN 4 MS STEPS.  SO 125 LOOPS IS 500 MS
	MOVWF DLY
	CALL LONGDLY
	GOTO MAINLOOP	
;
;_________________________________________________________________________
;			SUBROUTINES FOLLOW
;________________________________________________________________________
;
GETLED;		SUBROUTINE TO SET A/D TO SELECT/READ LED PIN-6/GPIO-1 
	MOVLW B'00001001'; ALSO STOPS ANY CONVERSION IN PROGRESS 
	MOVWF ADSEL;
	CALL WAIT100US;  LET EVERYTHING SETTLE
	BSF ADSEL, 1;  START CONVERSION
	CALL WAIT100US; WAIT;
	MOVF ADHIGH, 0;  LOAD W WITH VALUE
	MOVWF ADSAVE;  SAVE DATA IN REGULAR REGISTER...NO WORRY ABOUT OVER-WRITE
	RETURN
;
;________________________________________________________________________
;
GETRATE;	SUBROUTINE TO SET A/D TO SELECT/READ LED PIN-3/GPIO-4 
	MOVLW B'00001101'; ALSO STOPS ANY CONVERSION IN PROGRESS 
	MOVWF ADSEL;
	CALL WAIT100US;  LET EVERYTHING SETTLE
	BSF ADSEL, 1;  START CONVERSION
	CALL WAIT100US; WAIT;
	MOVF ADHIGH, 0;  LOAD W WITH VALUE
	MOVWF ADSAVE;  SAVE DATA IN REGULAR REGISTER...NO WORRY ABOUT OVER-WRITE
	RETURN
;
;________________________________________________________________________
;
GETVCC;		SUBROUTINE TO SET A/D TO SELECT/READ VCC PIN-7/GPIO-0 
	MOVLW B'00000001'; ALSO STOPS ANY CONVERSION IN PROGRESS 
	MOVWF ADSEL;
	CALL WAIT100US;  LET EVERYTHING SETTLE
	BSF ADSEL, 1;  START CONVERSION
	CALL WAIT100US; WAIT; 
	MOVF ADHIGH, 0;  LOAD W WITH VALUE
	MOVWF ADSAVE;  SAVE DATA IN REGULAR REGISTER...NO WORRY ABOUT OVER-WRITE
	RETURN
;
;________________________________________________________________________________________
;
WAIT100US;     SUBROUTINE  WAITS 100 US AND CLEARS WATCH-DOG TIMER
			;SINCE MOST OF THE PROGRAM IS WAIT-LOOPS USING THIS SUBROUTINE
			;CALLS ARE ALWAYS LESS THAN 18 MS (WDT TIMEOUT PERIOD)
	MOVLW LOOPCNT;  LOAD CONSTANT VALUE     
	MOVWF LPCT;		INTO REGISTER
	CLRWDT;			CLEAR WATCH-DOG TIMER
WAITLP;				ACTUAL TIMER LOOP
	NOP;		MAIN LOOP=4 CLOCKS
	DECFSZ LPCT, 1;  NORMALLY THIS IS 1 CLOCK
	GOTO WAITLP;
	RETURN;		ENTRY AND EXIT (INC EXTERNAL CALL)  7 CLOCKS  
	;			PLUS EXTERNAL BSF AND BCF	~1 CLOCK
;				SO LOOP 23 TIMES OR 017H TIMES  (LOOPCNT S/B 017H)
;____________________________________________________________________________________________
;
WAIT4MS;	SUBROUTINE TO WAIT 4 MS  WHICH IS STEP-SIZE FOR RATE
	MOVLW D'040';  
	MOVWF DLY4MS;	
WAIT4MSLP;	
	CALL WAIT100US;  40 X 100uS GIVES 4 mS
	DECFSZ DLY4MS, 1;
	GOTO WAIT4MSLP
	RETURN
;
;____________________________________________________________________________________________________
;
LONGDLY;  PERIOD DELAY FROM 4 MS TO 128 MS IN 4 MS LOOPS
	MOVF DLY, 0;  MOVE 0-32 VALUE TO LOOP COUNTER  
	MOVWF DLYXMS;
	BTFSC STATUS, 2;  TEST FOR 0 COMING IN.  LOOP FAILS IN THAT CASE
	INCF DLYXMS, 1;  WAS 0 SO MAKE IT 1
WAITXMSLP;	
	CALL WAIT4MS
	DECFSZ DLYXMS, 1
	GOTO WAITXMSLP
	RETURN
;
;_________________________________________________________________________________
;
	END

