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.
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
; 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