Generating Sinewaves on a PIC16F628

also: theory | 16F628 example | 3 Phase sines

At school we used a pair of equations to generate sinewaves.

 x = x + y / n
 y = y - x / n

Itterate them and apply y or x to a D to A converter. You get a sine wave as long at n is quite large.

One of the most striking things to me is the stability of the prediction.

The amplitude remains constant of very many cycles.

using a PIC 16F628 to generate sine waves where n = 256

Here is a bit of PIC 16F628 code:

INT_SERVICE_TMR2
	
OStimeSlice

	MOVFW	OSloops
	MOVWF	OScnt

OStimeSlice1
	BCF		PIR1, TMR2IF

	; want x=x+y/256
	; want y=y-x/256
	
	; x=x+y/256
	BCF		STATUS,C
	MOVFW	OSyh	;y/256
	ADDWF	OSxl,f

	; add the carry	
	BTFSC	STATUS,C
	INCF	OSxh,f
	
	
	; sign extend the MSB
	; add 0xFF is MSB if OSyh is set
	; note we add OSy
	BTFSC	OSyh,7
	DECF	OSxh,f
	

	; y=y-x/256
	BCF		STATUS,C
	MOVFW	OSxh;x/256
	SUBWF	OSyl,f    ;x/256

	BTFSS	STATUS,C
	DECF	OSyh,f

	; now subtract sign extended OSx 

;	MOVLW	0
;	BTFSC	OSxh,7
;	MOVLW	0xff
;	SUBWF	OSyh,f

	; if MSB of OSxh,7 is set then sign extend and subtract -1 from OSyh by adding 1 to OSyh 
	BTFSC	OSxh,7
	INCF	OSyh,f

	DECFSZ	OScnt
	GOTO	OStimeSlice1


; if you use OSyh at this point you get a discontinuty at the peaks
; if you use OSxh at this point you get a smaller discontinuty on the way up

;	MOVFW	OSyh	;y/256
	MOVFW	OSxh	;y/256
	ADDWF	OSoffset,w
	BANKSEL	CCPR1L
	MOVWF	CCPR1L

	return
	

I set up the PWM using

	ifdef buildPWM

	; Configure Tmr 1
	MOVLW	0x0 | 1<<TMR1ON | 3 <<T1CKPS0 
	MOVWF	T1CON

	CLRF	OSxh	
	CLRF	OSxl	
	CLRF	OSyh	
	CLRF	OSyl	

	MOVLW	0x1f
	MOVWF	OSxhStart
	CLRF	OSxlStart
	MOVLW	0x01
	MOVWF	OSloops
	MOVLW	0x40
	MOVWF	OSoffset

	endif

and

PWinit	; set up the PWM
	ifdef buildPWM

	; Move the PWM period into PR2
	
	MOVLW	0
	CALL	EEread	

	BANKSEL	PR2
	MOVWF	PR2
	
	MOVLW	0
	MOVWF	TRISB

	MOVLW	1
	CALL	EEread	

	BANKSEL	CCPR1L
	MOVWF	CCPR1L
		
	MOVLW	1 << TMR2ON
	MOVWF	T2CON
	
	BANKSEL	CCP1CON
	MOVLW	1<< CCP1X | 1<< CCP1Y | ( .12 << CCP1M0	)
	MOVWF	CCP1CON

	;
	; init SHM sinewave generator.
	;

	MOVFW	OSxhStart
	MOVWF	OSxh
	
	MOVFW	OSxlStart
	MOVWF	OSxl
	
	CLRF	OSyh
	CLRF	OSyl

	endif	

	RETURN

This was added to: http://www.dougrice.plus.com/hp/freq/freq.htm

8 bit version with N=16

	; x=x+y/16
	BCF		STATUS,C
	SWAPF	OSyh,w	;y/256
	; sign extend OSyh
	ANDLW	0x0F
	BTFSC	OSyh,7
	IORLW	0xF0
	
	ADDWF	OSxh,f

	; add the carry	
	BTFSC	STATUS,C
	INCF	OSxh,f

	; y=y-x/16
	BCF		STATUS,C
	SWAPF	OSxh,w	;y/256
	; sign extend OSxh
	ANDLW	0x0F
	BTFSC	OSxh,7
	IORLW	0xF0

	SUBWF	OSyh,f    ;x/256

	BTFSS	STATUS,C
	DECF	OSyh,f

	MOVFW	OSxh	;y/256
	ADDWF	OSoffset,w
	BANKSEL	CCPR1L
	MOVWF	CCPR1L


;**************************************************************************
; SR002.ASM
;
; PROGRAM: Simple Serial Project 
;
; DESCRIPTION: 
;	simple serial project that receives serial commands
;   spaces are important
;
; Serial Commands:-
;
; File Regiters
;	<CR>wAADD;		write DD to register AA
;	<CR>rAA;  		read AA and output to serial port
;
; EEPROM
;	<CR>pAADD;		write DD to EEPROM register AA
;	<CR>gAA;  		read EEPROM register AA and output to serial port
;
; PRIPHERALS
;	<CR>f;			init PWM
;	; sets up PWM module 
;	W92FF;	- PR2 	 - set PWM period max
;	W1532;	- CCPR1L	 - Duty Cycle / ON period
;	W8600;	- TRISB	 - All Outputs
;	W1204;	- T2CON	 - Set up Tmr 2 
;	W173C;	- CCP1CON - Set up as PWM module.
;	W9265;	- PR2 	 - set PWM period for 10Khz if 4Mhz crystal.
;

;
; SERIAL PORT CONTROL:
;
;	PORT A0 is Serial input
;	PORT A0 is serial output
;
;	usb gmus-03 USB Serial Adapter
;
;	TX  D9 Pin 3 -[4k7]----+-----PA0
;	RX  D9 Pin 2 ----------/
;
;	GND D9 Pin 5 ---------------- 0V
; 
; AUTHOR:  Douglas Rice
; Copyright 2004
;
;	Crystal:	4MHz
;
;	I/O used:-
;
;	; Port B is used for the LCD
;
;
;**************************************************************************


;--------------------------------------------------------------------------
; Sec 0.  #Defines tofor different chips
;--------------------------------------------------------------------------

; uncomment only one of these
;

;#define pic16F84 		1
#define pic16F628 	1
;#define pic16F876 	1
;#define pic12F675 	1

    LIST    w=0, R=DEC

;--------------------------------------------------------------------------
; Sec 0.1 #Defines for 16F84
;--------------------------------------------------------------------------

	ifdef pic16F84
    LIST    P=16F84, R=DEC
	INCLUDE "p16F84.inc"       

	__idlocs  0x0084
	__config  _XT_OSC & _PWRTE_ON & _WDT_OFF
	
	cblock 	0x0c
	endc
	

PORT_RS232	  EQU  PORTA 	    
TRIS_RS232	  EQU  TRISA 	    
RS232tx         EQU  0	; Serial Out
RS232rx         EQU  0	; Serial In needs to be equal to BUTTON_RS232

	
	endif	

;--------------------------------------------------------------------------
; Sec 0.2 #Defines for 16F628
;--------------------------------------------------------------------------

	ifdef pic16F628
#define 	buildPWM	1
    LIST    P=16F628, R=DEC
	INCLUDE "p16F628.inc"       

	__idlocs  0x0628
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_CLKOUT  & _MCLRE_OFF & _LVP_OFF
	
	cblock 0x20
	endc

; *********** I/O EQUATES **************

PORT_RS232	  EQU  PORTA 	    
TRIS_RS232	  EQU  TRISA 	    
RS232tx         EQU  0	; Serial Out
RS232rx         EQU  0	; Serial In needs to be equal to BUTTON_RS232


	endif

;--------------------------------------------------------------------------
; Sec 0.3 #Defines for 16F876
;--------------------------------------------------------------------------

	ifdef pic16F876
#define 	buildPWM	1
    	LIST    P=16F876, R=DEC
	INCLUDE "p16F876.inc"       

	__idlocs  0x0876
	__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_ON & _WDT_OFF & _BODEN_OFF & _PWRTE_ON  & _HS_OSC & _LVP_OFF
	
	cblock 0x20
	endc

; *********** I/O EQUATES **************

PORT_RS232	  EQU  PORTA 	    
TRIS_RS232	  EQU  TRISA 	    
RS232tx         EQU  0	; Serial Out
RS232rx         EQU  0	; Serial In needs to be equal to BUTTON_RS232


	endif


;--------------------------------------------------------------------------
; Sec 0.4 #Defines for 12F675
;--------------------------------------------------------------------------

	ifdef pic12F675
    	LIST    P=12F675, R=DEC

	INCLUDE "p12F675.inc"       
	__idlocs  0x0675
	__config  _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF 

	
	cblock 0x20
	endc

; *********** I/O EQUATES **************

PORT_RS232  EQU  GPIO 	    
TRIS_RS232  EQU  TRISIO 	    
RS232tx     EQU  5	; Serial Out
RS232rx     EQU  5	; Serial In needs to be equal to BUTTON_RS232

PORTA		EQU  GPIO 	    		
PORTB		EQU  GPIO 	    		

TRISA		EQU  TRISIO 	    
TRISB		EQU  TRISIO 	    
	endif



;--------------------------------------------------------------------------
; Sec 1. Equates and Constants
;--------------------------------------------------------------------------
; The General Purpose Registers start at the end of the 
; Special Purpose Registers.

; IPMentState values
; in normal running or in time setting modes
;

; DoTimeSlice bits
; these bits are set to schedule a timer chain event
DTsS4event	EQU	0	; 

RUN_BUFF	EQU	0	; 

; IPtrigMenu
DTSFast			EQU	0

;--------------------------------------------------------------------------
; Sec 1.1 Button and LED 
;--------------------------------------------------------------------------

BUTTON_RS232	EQU	RS232rx	; EDG  - Bottom Buttom
BUTTON_DOWN	EQU	6	; EDG  - Bottom Buttom

;--------------------------------------------------------------------------
; Sec 2.0 Variables
;--------------------------------------------------------------------------
; Variables start 0x0C
;

;	DoTimeSlice Bits, to schedule, set bit

	cblock 	
DoTimeSlice

IPnew
IPlast
IPbuttonEvent

IPnewFast
IPlastFast
IPbuttonEventUp

IPtrigMenu

; variables used by Serial input and output routines
RStxTemp
RSloopCnt
RSdelayCnt
RSin
RSout

; Serial input buffer
RSipBuffCnt ; input buffer counter
; start of buffer
RScmd
RSAa		;
RSaA		;
RSDd		;
RSdD		;
RSterminator
; end of buffer

; temporary variables
RSaddr
RSdata
;



; Sinewave Oscillator variables

OSxhStart
OSxlStart
OSloops
OSoffset

; working variables
OSxh
OSxl
OSyh
OSyl
OScnt

	ENDC


	



;--------------------------------------------------------------------------
; Sec 3. MACROS
;--------------------------------------------------------------------------


TEST_STRADDLE	MACRO	START
	if high( $ ) != high( START ) 
	    Error "Table straddles Page Boundary " + Start
	endif
	endm

;--------------------------------------------------------------------------
; Sec 4. Program Code
;--------------------------------------------------------------------------
	ORG     0       
	GOTO    Start

	ORG 	4
	RETFIE
	GOTO 	Intrtn

;--------------------------------------------------------------------------
; Sec 4.1	Main Program Init Code
;--------------------------------------------------------------------------

Start

	CALL 	INinit
	CALL	INsayHello	
	GOTO	MainLoop


INT_SERVICE_TMR2
	
OStimeSlice

	MOVFW	OSloops
	MOVWF	OScnt

OStimeSlice1
	BCF		PIR1, TMR2IF

	; want x=x+y/256
	; want y=y-x/256
	
	; x=x+y/256
	BCF		STATUS,C
	MOVFW	OSyh	;y/256
	ADDWF	OSxl,f

	; add the carry	
	BTFSC	STATUS,C
	INCF	OSxh,f
	
	
	; sign extend the MSB
	; add 0xFF is MSB if OSyh is set
	; note we add OSy
	BTFSC	OSyh,7
	DECF	OSxh,f
	

	; y=y-x/256
	BCF		STATUS,C
	MOVFW	OSxh;x/256
	SUBWF	OSyl,f    ;x/256

	BTFSS	STATUS,C
	DECF	OSyh,f

	; now subtract sign extended OSx 

;	MOVLW	0
;	BTFSC	OSxh,7
;	MOVLW	0xff
;	SUBWF	OSyh,f

	; if MSB of OSxh,7 is set then sign extend and subtract -1 from OSyh by adding 1 to OSyh 
	BTFSC	OSxh,7
	INCF	OSyh,f

	DECFSZ	OScnt
	GOTO	OStimeSlice1


; if you use OSyh at this point you get a discontinuty at the peaks
; if you use OSxh at this point you get a smaller discontinuty on the way up

;	MOVFW	OSyh	;y/256
	MOVFW	OSxh	;y/256
	ADDWF	OSoffset,w
	BANKSEL	CCPR1L
	MOVWF	CCPR1L

	return
	

;--------------------------------------------------------------------------
; Sec 4.2	Main Program 
;--------------------------------------------------------------------------

MainLoop	
		BTFSC	PIR1, TMR2IF
		CALL	INT_SERVICE_TMR2


		CALL	IPtimesliceFast
		
		; test for rising edge
		BTFSC	IPbuttonEventUp,BUTTON_RS232	; RS232 input start 
		CALL	IPrs232
		
		MOVF	DoTimeSlice,w
		Bz		MainLoop

		BTFSC	DoTimeSlice,RUN_BUFF
		CALL	DLrunBuff



	


		GOTO 	MainLoop
		


;--------------------------------------------------------------------------
; Sec 5.	Subroutines, procedures and functions
;--------------------------------------------------------------------------


;--------------------------------------------------------------------------
; Sec 5.1	Button Poll Routine
;--------------------------------------------------------------------------
		
IPtimeslice
		;	--_____	button press
		;	----___	
		
		;	__-----  /IPnew
		;	----___  IPlast
		;	__--___  
		;
		;
		;
		; This reads all Port A inputs and looks for Press
		MOVFW	IPnew
		MOVWF	IPlast
		MOVFW	PORTA
		MOVWF	IPnew
		; IP last contains new setting, IPlast contains previous
		; look for falling edges
		COMF	IPnew,W
		ANDWF	IPlast,W
		; now force IPbuttonEvent bits to high for new pressed button
		; the service routine should reset the bit to clear the event.
		IORWF	IPbuttonEvent,F
		RETURN

IPtimesliceFast
		; Look for rising edges
		MOVFW	IPnewFast
		MOVWF	IPlastFast
		MOVFW	PORT_RS232
		MOVWF	IPnewFast

		COMF	IPlastFast,W
		ANDWF	IPnewFast,W
		IORWF	IPbuttonEventUp,F
		RETURN
;--------------------------------------------------------------------------
; Sec 5.2	
;--------------------------------------------------------------------------

;--------------------------------------------------------------------------
; Sec 5.2	.1 run process on request
;--------------------------------------------------------------------------

DLrunBuff
	BCF	DoTimeSlice,RUN_BUFF
;	MOVFW	'#'
;	CALL 	RStxChar

	
	MOVFW	RSin			
	CALL	RSbuffInput
	return
	
	


;--------------------------------------------------------------------------
; Sec 5.3	 Button Input functions
;--------------------------------------------------------------------------


IPdownPressed 
	BCF IPbuttonEvent,BUTTON_DOWN
	return


IPrs232
	BCF IPbuttonEventUp,BUTTON_RS232
	GOTO RSrs232in 	


;--------------------------------------------------------------------------
; Sec 5.4	 Clock Chain Routine
;--------------------------------------------------------------------------
		
CLtimeslice
		;
		BTFSS	INTCON,T0IF
		RETURN

		; TMR0 timeout
		BCF		INTCON,T0IF
		BSF		DoTimeSlice,DTsS4event
		
		CALL	IPtimeslice
		RETURN


;--------------------------------------------------------------------------
; Sec 5.5 	Serial Input Routine
;--------------------------------------------------------------------------

;**************************************************
RSrs232in

; Test is in main loop or uncomment code below to
; spin for a start bit 
;		CLRWDT
;		BTFSS	PORT_RS232,RS232rx	
;		GOTO	RSrs232in		
		
		
		CALL	RSdelayBit			; delay through Stop Bit
		CALL 	RSdelayHalfBit		; delay halfway into first bit

		movlw	8
		movwf	RSloopCnt
RSrs232inL0
		MOVFW	PORT_RS232
		ANDLW	 1<< RS232rx		; mask off bit
		ADDLW	-1<< RS232rx		; use ripple carry to move into C
		RRF		RSin,F
		
		CALL	RSdelayBit
		DECFSZ	RSloopCnt,f
		goto	RSrs232inL0

		; test for Stop bit
		COMF	RSin,f
		BSF		DoTimeSlice,RUN_BUFF
		RETURN
		

;--------------------------------------------------------------------------
; Sec 5.6 	Serial Output Routines
;--------------------------------------------------------------------------


RSwrtHexNibble	; currently only displays 0..9, A..F
	ANDLW	0x0F
	ADDLW	0x06	; is it A..F, if so trigger a digit overflow
	SKPNDC
	ADDLW	7; subtract 10, then add 'A'-'0'
	ADDLW	0x30-6	; Subtract extra 6 added to cause DC
	MOVWF	RSout
	GOTO	RStxChar

RStxChar
	;
	; Output Start Bit
	; Start bit is low, data bits are inverted
	;
	
	movwf	RStxTemp
	comf	RStxTemp,f
	BCF		PORT_RS232,RS232tx

	; Make RS232 pin an ouput while transmitting character
	BANKSEL  TRIS_RS232		
	BCF		TRIS_RS232,RS232tx
	BANKSEL  PORT_RS232		

	; 1200 baud output
	; move the char into RStxtemp, it is destroyed.
	;Start Bit
	BSF		PORT_RS232,RS232tx

	call	RSdelayBit
	movlw	8
	movwf	RSloopCnt

RStxCharLp1
	
	; After start bit, which is 1, then test each bit
	; I need to set PA:0 to same as LSB RStxTemp
	; this compares PA:0 with RStxTemp so see if it needs toggling
	; The xorwf PORT_RS232,f causes the bit to be toggled if required.
	
	RRF		RStxTemp,f
	movfw	STATUS
	andlw	1 << C			; mask off bit
	addlw   ( 1 << RS232tx) -1	; shift bit by using a ripple carry
	xorwf	PORT_RS232,W			; Doeas output need toggling ?
	andlw	1 << RS232tx		; Mask off output pin	
	xorwf	PORT_RS232,f			; Toggle output pin if needed	
	call	RSdelayBit			; delay bit
	
	
	decfsz	RSloopCnt,f
	goto	RStxCharLp1

	BCF		PORT_RS232,RS232tx
	call	RSdelayBit	; apply stop bit

	; Make RS232 pin an input so that main loop can test for start bit
	BANKSEL  TRIS_RS232		
	BSF		TRIS_RS232,RS232tx
	BANKSEL  PORT_RS232		

	RETURN


; timing functions to delay serial routines for a bit or half bit.

RSdelayHalfBit		
		MOVLW	0x1D		; shorten delay as edge detector takes about 22 us for 4800 baud
		GOTO	RSdelayBit0			

RSdelayBit		
		NOP
		MOVLW	0x40	 ; for 4800 baud	

RSdelayBit0			
		MOVWF	RSdelayCnt
RSdelayBit1	DECFSZ	RSdelayCnt,f		; 1
		GOTO	RSdelayBit1		; 2 clk
		CLRWDT
		RETURN



;--------------------------------------------------------------------------
; Sec 5.7 	Serial Output Format Routines
;--------------------------------------------------------------------------

RSasciiToNibble
	MOVWF	RSin
	; if 0..1 then 0x30 to 0x39
	; if A..F then 0x41 to 0x46
	; if a..f then 0x61 to 0x66
	; test if bit 4 set and assume a letter or number
	BTFSS	RSin,4
	ADDLW	0x09		; letter so add 9 
	ANDLW	0x0F		; mask of nibble
	return


;--------------------------------------------------------------------------
; Sec 5.8 	Serial Input Buffer Routine
;--------------------------------------------------------------------------

; take serial input CAADD and put into buffer 
; if char id ; the do command
; if char is CR reset buffer pointer
; if buff end then reset buff pointer


RSipbuffStart	EQU RScmd 
RSipbuffEnd	EQU RSterminator

RSbuffInput
	MOVWF	RSin
	; look for line feed and reset buff cnt
	ADDLW	-0x0D
	BNZ		RSbuffInput1
	MOVLW	RSipbuffStart
	MOVWF	RSipBuffCnt
	RETURN

RSbuffInput1		
	; end of line command - do command
	ADDLW	-';'+0x0D
	BNZ		RSbuffInput2
	GOTO	RSbuffInputProcess

RSbuffInput2
	; Store the current time into the next register.
	MOVFW	RSipBuffCnt
	MOVWF	FSR
	MOVFW	RSin
	MOVWF	INDF
	INCFSZ	RSipBuffCnt,f
	MOVFW	RSipBuffCnt

	ADDLW	-(RSipbuffEnd+1)
	; Check if the end of memory
	SKPZ	
	GOTO	RSbuffInputEnd1
	MOVLW	RSipbuffStart
	MOVWF	RSipBuffCnt

	; reset cursor
	MOVLW	0x0D
	CALL 	RStxChar
	RETURN
	

RSbuffInputProcess
	MOVLW	RSipbuffStart
	MOVWF	RSipBuffCnt

	MOVFW	RSAa
	; if 0..1 then 0x30 to 0x39
	; if A..F then 0x41 to 0x46
	; if a..f then 0x61 to 0x66
	; test if bit 4 set and assume a letter or number

	BTFSS	RSAa,4
	ADDLW	0x09		; letter so add 9 
	ANDLW	0x0F		; mask of nibble
	MOVWF	RSin
	SWAPF	RSin,F
	
	MOVFW	RSaA
	BTFSS	RSaA,4
	ADDLW	0x09		; letter so add 9 
	ANDLW	0x0F		; mask of nibble
	ADDWF	RSin,w
	MOVWF	RSaddr

	MOVFW	RSDd
	BTFSS	RSDd,4
	ADDLW	0x09		; letter so add 9 
	ANDLW	0x0F		; mask of nibble
	MOVWF	RSin
	SWAPF	RSin,F
	
	MOVFW	RSdD
	BTFSS	RSdD,4
	ADDLW	0x09		; letter so add 9 
	ANDLW	0x0F		; mask of nibble
	ADDWF	RSin,w
	MOVWF	RSdata
	
	; CALL 	RStxChar

	; got to end of buffer so process. does not allow for backspace

	; Write to file register
	MOVLW	-'w'
	ADDWF	RScmd,w	; test to see if command is s, if so save into register.
	bnz  	RSbuffInput3		
	
	MOVFW	RSaddr
	MOVWF	FSR
	
	MOVFW	RSdata
	MOVWF	INDF

	
	MOVLW	'*'
	CALL 	RStxChar
	GOTO	RSbuffInputEnd
	
	
RSbuffInput3

	; put octet in EEPROM
	MOVLW	-'p'
	ADDWF	RScmd,w	; test to see if command is s, if so save into register.
	bnz  	RSbuffInput4		
	
	MOVFW	RSaddr
	CALL	EEsetAddr

	BANKSEL	RSdata
	MOVFW	RSdata
	CALL	EEwrt

	MOVFW	RSdata
	MOVWF	INDF
	
	MOVLW	'*'
	CALL 	RStxChar

	GOTO	RSbuffInputEnd
	
	
	
		
RSbuffInput4
	; read from file register
	MOVLW	-'r'
	ADDWF	RScmd,w	; test to see if command is s, if so save into register.
	bnz  	RSbuffInput5

	MOVFW	RSaddr
	MOVWF	FSR
	
	MOVFW	INDF
	MOVWF	RSin

RSbuffInput4display
	MOVLW	'='
	CALL 	RStxChar
	
	SWAPF	RSin,w
	CALL	RSwrtHexNibble

	MOVFW	RSin
	CALL	RSwrtHexNibble
	
	GOTO	RSbuffInputEnd


RSbuffInput5
	; get from EEPROM register
	MOVLW	-'g'
	ADDWF	RScmd,w	; test to see if command is s, if so save into register.
	bnz  	RSbuffInput6

	MOVFW	RSaddr
	CALL	EEread
	MOVWF	RSin
	
	GOTO	RSbuffInput4display	


RSbuffInput6
	; Initilize PWM
	MOVLW	-'f'
	ADDWF	RScmd,w	; test to see if command is s, if so save into register.
	bnz  	RSbuffInput7
	CALL	PWinit;
	MOVLW	'*'
	CALL 	RStxChar
	GOTO	RSbuffInputEnd
			
RSbuffInput7

RSbuffInputEnd

	MOVLW	0x0D
	CALL 	RStxChar
		
	MOVLW	0x0A
	CALL 	RStxChar

RSbuffInputEnd1

    return

;--------------------------------------------------------------------------
; Sec 5.9 Initilization code - 
;--------------------------------------------------------------------------


INinit
	; Enable Interupts
	MOVLW	H'00'
	MOVWF	INTCON

	CLRF PORT_RS232 ;Initialize PORT_RS232 by setting
	;output data latches
	
	ifdef pic12F675
	; get the Oscillator calibration

	;MOVLW	0x6C		; load the Calib
	BSF		STATUS,RP0
	CALL 	OscCalValue
	MOVWF	OSCCAL
	
	BANKSEL 	CMCON
	MOVLW 	0X07 ;Turn comparators off and
	MOVWF 	CMCON ;enable pins for I/O
	
	BANKSEL 	ANSEL
	CLRF	ANSEL	

	endif



	ifdef pic16F628
	BANKSEL CMCON
	MOVLW 0X07 ;Turn comparators off and
	MOVWF CMCON ;enable pins for I/O

	endif

	ifdef pic16F876
     ;make AtoD inputs digital
	BANKSEL ADCON1
	MOVLW 0X07 ;Turn comparators off and
	MOVWF ADCON1 ;enable pins for I/O
	endif



	banksel	TRISB
	MOVLW	0XF0
	MOVWF	TRISB
	BSF		TRIS_RS232, RS232tx 	; Make PORT_RS232 3:0 INPUTS.


	banksel	RSipbuffStart
	; reset input buffer
	MOVLW	RSipbuffStart
	MOVWF	RSipBuffCnt

	; Change Prescaler
	CLRWDT

	; Configure Tmr 0
	BSF		STATUS,RP0
	; Set up prescaller for 8192 / 16 = 512 ticks perseconds.

	MOVLW	0x0 + 2 	; For Tmr0 0=/2, 1=/4, 2=/8,3=/16
	MOVWF	OPTION_REG
	BCF		STATUS,RP0

	ifdef buildPWM

	; Configure Tmr 1
	MOVLW	0x0 | 1<<TMR1ON | 3 <<T1CKPS0 
	MOVWF	T1CON

	CLRF	OSxh	
	CLRF	OSxl	
	CLRF	OSyh	
	CLRF	OSyl	

	MOVLW	0x1f
	MOVWF	OSxhStart
	CLRF	OSxlStart
	MOVLW	0x01
	MOVWF	OSloops
	MOVLW	0x40
	MOVWF	OSoffset

	endif

	CLRF	DoTimeSlice	
	CLRF	IPbuttonEvent
	CLRF	IPbuttonEventUp
	

	return

INsayHello	
	; print out power on message
	MOVLW	0x0D
	CALL 	RStxChar
		
	MOVLW	0x0A
	CALL 	RStxChar

	MOVLW	'S'
	CALL 	RStxChar
		
	MOVLW	'R'
	CALL 	RStxChar
		
	MOVLW	0x0D
	CALL 	RStxChar
		
	MOVLW	0x0A
	CALL 	RStxChar
	return


;--------------------------------------------------------------------------
; Sec 5.10 	EEprom Routines for 16F628
;--------------------------------------------------------------------------

EEread		
		; w contains address
		banksel	EEADR	
		MOVWF	EEADR
		BSF		EECON1,RD
		MOVFW	EEDATA
		banksel	0	
		RETURN

EEsetAddr
		banksel	EEADR
		MOVWF	EEADR
		RETURN
		
EEwrt		; blocking, EEADR and EEDATA set up.
		;		BSF	STATUS,RP0
		banksel 	EEDATA
		MOVWF	EEDATA
		BCF		INTCON,GIE
		BCF		EECON1,EEIF
		BSF		EECON1,WREN
		MOVLW	0x55
		MOVWF	EECON2
		MOVLW	0xAA
		MOVWF	EECON2
		BSF		EECON1,WR
		; Now wait for EEwrt to finish write
EEwaitForWrt	; block until EEPROM write has finished.
		BCF		EECON1,WREN	; disable EROM
		BTFSC	EECON1,WR
		GOTO	EEwaitForWrt
		BCF		EECON1,EEIF	; EEPROM finished
		; BCF	STATUS,RP0

		banksel	0	
		RETURN
		
;--------------------------------------------------------------------------
; Sec 5.11	Routines to set up PWM on 16F628
;--------------------------------------------------------------------------




PWinit	; set up the PWM
	ifdef buildPWM

	; Move the PWM period into PR2
	
	MOVLW	0
	CALL	EEread	

	BANKSEL	PR2
	MOVWF	PR2
	
	MOVLW	0
	MOVWF	TRISB

	MOVLW	1
	CALL	EEread	

	BANKSEL	CCPR1L
	MOVWF	CCPR1L
		
	MOVLW	1 << TMR2ON
	MOVWF	T2CON
	
	BANKSEL	CCP1CON
	MOVLW	1<< CCP1X | 1<< CCP1Y | ( .12 << CCP1M0	)
	MOVWF	CCP1CON

	;
	; init SHM sinewave generator.
	;

	MOVFW	OSxhStart
	MOVWF	OSxh
	
	MOVFW	OSxlStart
	MOVWF	OSxl
	
	CLRF	OSyh
	CLRF	OSyl

	endif	

	RETURN
	
	
	

		


;--------------------------------------------------------------------------
; Sec 6.0		Interrupt Routines
;--------------------------------------------------------------------------

Intrtn		
		RETFIE

;--------------------------------------------------------------------------
; Program End
;--------------------------------------------------------------------------
	ifdef pic12F675
	
	org	0x3FD
	RETLW	0x6C
	RETLW	0x6C
OscCalValue	
	RETLW	0x6C
	endif
LastProgWord

;--------------------------------------------------------------------------
; Sec 7.0		EEPROM data
;--------------------------------------------------------------------------
		ORG	0x2100
		; first 2 on and off are general ones
		DE	.100,.50  ; 4

	cblock 	
LastVar
	endc
               END



image