The key to WavePOD is the PIC firmware. Below is the source for the 16CE625-20. This code is included in the download files and provides a number of SAWTOOTH and SQUARE waveforms for WavePOD. There is also a Sine Wave generator (using inline PortB setting).
The last WaveLoop is a 32 step arbitrary waveform generator with frequency set by a 32 bit Phase Accumulator. This code allows WavePOD to generate waveforms of very accurate frequency with a sample rate of 125KHz. To modify this WaveLoop, calculate 32 hex values corresponding to points on your desired waveform. Calculate the phase increment required to step through the whole table in one period.
For those with a basic knowledge of PIC assembly, modifying and extending the WaveLoops provided should be straightforward. To make the process of learnng this code easier, we've picked out these 16 WaveLoops and shown them with screenshots of the waveforms generated here.
;**************************************************************************** ; BitScope WavePOD PIC based Function Generator ;**************************************************************************** ; ; Author:- N.J.Jackson ; MetaChip P/L ; ; Copyright 2001-2003 Metachip Pty. Ltd. ; ; PIC Device 16CE625-20 200nS execution time page ;************************************************************************** ; Processor options and includes ;************************************************************************** list p=PIC16CE625, n=92 include <P16CE625.INC> ; include for this chip __config H'0002' ; Normal Speed, No Watchdog ; Power Up Timer, Code Protect __idlocs H'0001' ; Default Batch Number - 0001 radix dec ; default radix is decimal JMP_PAGE equ 7 ; jump page 0x7f0->0x7ff (2K of program MEM) ; only implement 0->7f (in top of Program memory) page ;**************************************************************************** ; Port Pin names ;**************************************************************************** RA0 equ 0 ; port bit 0 Refer to port pins RA1 equ 1 ; port bit 1 RA2 equ 2 ; port bit 2 RA3 equ 3 ; port bit 3 RA4 equ 4 ; port bit 4 RB0 equ 0 ; port bit 0 RB1 equ 1 ; port bit 1 RB2 equ 2 ; port bit 2 RB3 equ 3 ; port bit 3 RB4 equ 4 ; port bit 4 RB5 equ 5 ; port bit 5 RB6 equ 6 ; port bit 6 RB7 equ 7 ; port bit 7 ;************************************************************************** ; Set initial condition for Ports ;************************************************************************** ; PIC is set tri state at reset PORTA_INIT equ 0x1f ; IO all '1' TRISA_INIT equ 0x1f ; RA0..RA3 IN's, TOCI is INPUT PORTB_INIT equ 0x80 ; Start off with 80 (Vout = 0) TRISB_INIT equ 0x00 ; all inputs OPTION_INI equ 0xff ; INTCON_INI equ 0x20 ; none to start TRISB_IN equ 0xff ; all inputs TRISB_OUT equ 0x00 ; all outputs page ;************************************************************************** ; Register definition - ByteCode machine internal registers ;************************************************************************** REG_BASE equ 0x20 ; start internal registers here gen_0 equ REG_BASE + 0 ; general purpose registers gen_1 equ REG_BASE + 1 ; gen_2 equ REG_BASE + 2 ; gen_3 equ REG_BASE + 3 ; page ;************************************************************************** ; Set up block of registers that may be used for WaveLoops ;************************************************************************** ; Block of 48 GP registers that may be used for WaveLoops WAV_BASE equ 0x30 ; WaveLoop Registers WAV0..WAV47 WAV_0 equ WAV_BASE + 0 ; WAV-0 WAV_1 equ WAV_BASE + 1 ; WAV-1 WAV_2 equ WAV_BASE + 2 ; WAV-2 WAV_3 equ WAV_BASE + 3 ; WAV-3 WAV_4 equ WAV_BASE + 4 ; WAV-4 WAV_5 equ WAV_BASE + 5 ; WAV-5 WAV_6 equ WAV_BASE + 6 ; WAV-6 WAV_7 equ WAV_BASE + 7 ; WAV-7 WAV_8 equ WAV_BASE + 8 ; WAV-8 WAV_9 equ WAV_BASE + 9 ; WAV-9 WAV_10 equ WAV_BASE + 10 ; WAV-10 WAV_11 equ WAV_BASE + 11 ; WAV-11 WAV_12 equ WAV_BASE + 12 ; WAV-12 WAV_13 equ WAV_BASE + 13 ; WAV-13 WAV_14 equ WAV_BASE + 14 ; WAV-14 WAV_15 equ WAV_BASE + 15 ; WAV-15 WAV_16 equ WAV_BASE + 16 ; WAV-16 WAV_17 equ WAV_BASE + 17 ; WAV-17 WAV_18 equ WAV_BASE + 18 ; WAV-18 WAV_19 equ WAV_BASE + 19 ; WAV-19 WAV_20 equ WAV_BASE + 20 ; WAV-20 WAV_21 equ WAV_BASE + 21 ; WAV-21 WAV_22 equ WAV_BASE + 22 ; WAV-22 WAV_23 equ WAV_BASE + 23 ; WAV-23 WAV_24 equ WAV_BASE + 24 ; WAV-24 WAV_25 equ WAV_BASE + 25 ; WAV-25 WAV_26 equ WAV_BASE + 26 ; WAV-26 WAV_27 equ WAV_BASE + 27 ; WAV-27 WAV_28 equ WAV_BASE + 28 ; WAV-28 WAV_29 equ WAV_BASE + 29 ; WAV-29 WAV_30 equ WAV_BASE + 30 ; WAV-30 WAV_31 equ WAV_BASE + 31 ; WAV-31 WAV_32 equ WAV_BASE + 32 ; WAV-32 WAV_33 equ WAV_BASE + 33 ; WAV-33 WAV_34 equ WAV_BASE + 34 ; WAV-34 WAV_35 equ WAV_BASE + 35 ; WAV-35 WAV_36 equ WAV_BASE + 36 ; WAV-36 WAV_37 equ WAV_BASE + 37 ; WAV-37 WAV_38 equ WAV_BASE + 38 ; WAV-38 WAV_39 equ WAV_BASE + 39 ; WAV-39 WAV_40 equ WAV_BASE + 40 ; WAV-40 WAV_41 equ WAV_BASE + 41 ; WAV-41 WAV_42 equ WAV_BASE + 42 ; WAV-42 WAV_43 equ WAV_BASE + 43 ; WAV-43 WAV_44 equ WAV_BASE + 44 ; WAV-44 WAV_45 equ WAV_BASE + 45 ; WAV-45 WAV_46 equ WAV_BASE + 46 ; WAV-46 WAV_47 equ WAV_BASE + 47 ; WAV-47 page ;************************************************************************** ; Start of code and interrupt vectors ;************************************************************************** org 0x000 reset call init_0 ; initialize the PIC goto vector_0 ;************************************************ ; fall thru to WaveLoop table ;************************************************ org 0x004 ; put it at the int point vector_0 movlw JMP_PAGE ; high byte of table movwf PCLATH ; put it in the latch movf PORTA,W ; get the WaveLoop vector iorlw 0xf0 ; jam the read byte to f0-ff movwf PCL ; - Geronimo....! ; we just vectored up to the ; jump page in those 5 program words page ;**************************************************************************** ; Utility Code ;**************************************************************************** ; ; set up port initial conditions ; init_0 movlw 0x07 ; bits to kill comparator!! movwf CMCON ; tricky!! movlw PORTA_INIT ; initial value movwf PORTA ; into porta movlw TRISA ; movwf FSR ; point to TRISA movlw TRISA_INIT ; initial value tristate movwf INDF ; into tris register movlw PORTB_INIT ; initial value movwf PORTB ; into portb movlw TRISB ; movwf FSR ; point to TRISA movlw TRISB_INIT ; initial value tristate movwf INDF ; into tris register init_pic movlw OPTION_REG ; movwf FSR ; point to OPTION movlw OPTION_INI ; initial value movwf INDF ; into OPTION register movlw INTCON_INI ; initial value movwf INTCON ; into INTCON return ; ;********************************************************** ; timer counts 1..255 (2uS..257uS) ;********************************************************** us_timer ; entry here assumes count in W movwf gen_0 ; set timer t_1 nop ; nop ; decfsz gen_0,F ; start counting down goto t_1 ; loop til 0 nop ; return ; that is it ;********************************************************************** ; Vector code for WaveLoops ;********************************************************************** ; Sawtooth waveforms waveloop_0 ; loop time is 153.6uS - F=6.5104KHz movlw 0x80 ; movwf PORTB ; l_01 incf PORTB,f ; do it goto l_01 ; and loop waveloop_1 ; loop time is 26.04166KHz movlw 0x80 ; movwf PORTB ; movlw 4 ; increment the DAC by 4 l_11 addwf PORTB,f ; do it goto l_11 ; and loop waveloop_2 ; loop time is 52.08333KHz movlw 0x80 ; movwf PORTB ; movlw 8 ; increment the DAC by 8 l_21 addwf PORTB,f ; do it goto l_21 ; and loop waveloop_3 ; loop time is ??? Hz movlw 0x80 ; movwf PORTB ; movlw 0x55 ; into w l_31 xorwf PORTB,f ; do it incf PORTB,f ; this will look good!! addlw 11 ; prime number goto l_31 ; and loop waveloop_4 ; loop time is KHz movlw 0x80 ; movwf PORTB ; ; This code is simple in-line setting of the DAC values each 0.4uS for ; a 32 step loop. The values plugged in here are a SINE wave, but may ; be replaced with anything you like. Depending on how much program space ; you have, the number of steps can be anything. Using (say) 100 steps of 1uS ; will give exactly a 10KHz loop. Simply make a table of N values for your ; waveform and edit them into the code. l_41 movlw 153 ; WAV-1 movwf PORTB ; put it to the DAC movlw 177 ; WAV-2 movwf PORTB ; put it to the DAC movlw 199 ; WAV-3 movwf PORTB ; put it to the DAC movlw 219 ; WAV-4 movwf PORTB ; put it to the DAC movlw 234 ; WAV-5 movwf PORTB ; put it to the DAC movlw 246 ; WAV-6 movwf PORTB ; put it to the DAC movlw 253 ; WAV-7 movwf PORTB ; put it to the DAC movlw 255 ; WAV-8 movwf PORTB ; put it to the DAC movlw 253 ; WAV-9 movwf PORTB ; put it to the DAC movlw 246 ; WAV-10 movwf PORTB ; put it to the DAC movlw 234 ; WAV-11 movwf PORTB ; put it to the DAC movlw 219 ; WAV-12 movwf PORTB ; put it to the DAC movlw 199 ; WAV-13 movwf PORTB ; put it to the DAC movlw 177 ; WAV-14 movwf PORTB ; put it to the DAC movlw 153 ; WAV-15 movwf PORTB ; put it to the DAC movlw 128 ; WAV-16 movwf PORTB ; put it to the DAC movlw 103 ; WAV-17 movwf PORTB ; put it to the DAC movlw 79 ; WAV-18 movwf PORTB ; put it to the DAC movlw 57 ; WAV-19 movwf PORTB ; put it to the DAC movlw 37 ; WAV-20 movwf PORTB ; put it to the DAC movlw 22 ; WAV-21 movwf PORTB ; put it to the DAC movlw 10 ; WAV-22 movwf PORTB ; put it to the DAC movlw 3 ; WAV-23 movwf PORTB ; put it to the DAC movlw 1 ; WAV-24 movwf PORTB ; put it to the DAC movlw 3 ; WAV-25 movwf PORTB ; put it to the DAC movlw 10 ; WAV-26 movwf PORTB ; put it to the DAC movlw 22 ; WAV-27 movwf PORTB ; put it to the DAC movlw 37 ; WAV-28 movwf PORTB ; put it to the DAC movlw 57 ; WAV-29 movwf PORTB ; put it to the DAC movlw 79 ; WAV-30 movwf PORTB ; put it to the DAC movlw 103 ; WAV-31 movwf PORTB ; put it to the DAC movlw 128 ; WAV-32 movwf PORTB ; put it to the DAC goto l_41 ; and loop waveloop_5 ; loop time is 3uS - DAC inc is 4 ; F=5.20833 KHz movlw 0x80 ; movwf PORTB ; l_51 movlw 0 ; WAV-1 movwf PORTB ; put it to the DAC movlw 0 ; WAV-2 movwf PORTB ; put it to the DAC movlw 0 ; WAV-3 movwf PORTB ; put it to the DAC movlw 0 ; WAV-4 movwf PORTB ; put it to the DAC movlw 0 ; WAV-5 movwf PORTB ; put it to the DAC movlw 128 ; WAV-6 movwf PORTB ; put it to the DAC movlw 138 ; WAV-7 movwf PORTB ; put it to the DAC movlw 128 ; WAV-8 movwf PORTB ; put it to the DAC movlw 118 ; WAV-9 movwf PORTB ; put it to the DAC movlw 128 ; WAV-10 movwf PORTB ; put it to the DAC movlw 138 ; WAV-11 movwf PORTB ; put it to the DAC movlw 128 ; WAV-12 movwf PORTB ; put it to the DAC movlw 118 ; WAV-13 movwf PORTB ; put it to the DAC movlw 128 ; WAV-14 movwf PORTB ; put it to the DAC movlw 138 ; WAV-15 movwf PORTB ; put it to the DAC movlw 128 ; WAV-16 movwf PORTB ; put it to the DAC movlw 128 ; WAV-17 movwf PORTB ; put it to the DAC movlw 150 ; WAV-18 movwf PORTB ; put it to the DAC movlw 150 ; WAV-19 movwf PORTB ; put it to the DAC movlw 150 ; WAV-20 movwf PORTB ; put it to the DAC movlw 90 ; WAV-21 movwf PORTB ; put it to the DAC movlw 90 ; WAV-22 movwf PORTB ; put it to the DAC movlw 90 ; WAV-23 movwf PORTB ; put it to the DAC movlw 150 ; WAV-24 movwf PORTB ; put it to the DAC movlw 150 ; WAV-25 movwf PORTB ; put it to the DAC movlw 150 ; WAV-26 movwf PORTB ; put it to the DAC movlw 90 ; WAV-27 movwf PORTB ; put it to the DAC movlw 90 ; WAV-28 movwf PORTB ; put it to the DAC movlw 90 ; WAV-29 movwf PORTB ; put it to the DAC movlw 130 ; WAV-30 movwf PORTB ; put it to the DAC movlw 131 ; WAV-31 movwf PORTB ; put it to the DAC movlw 132 ; WAV-32 movwf PORTB ; put it to the DAC movlw 133 ; WAV-33 movwf PORTB ; put it to the DAC movlw 134 ; WAV-34 movwf PORTB ; put it to the DAC movlw 135 ; WAV-35 movwf PORTB ; put it to the DAC movlw 136 ; WAV-36 movwf PORTB ; put it to the DAC movlw 137 ; WAV-37 movwf PORTB ; put it to the DAC movlw 138 ; WAV-38 movwf PORTB ; put it to the DAC movlw 139 ; WAV-39 movwf PORTB ; put it to the DAC movlw 140 ; WAV-40 movwf PORTB ; put it to the DAC movlw 141 ; WAV-41 movwf PORTB ; put it to the DAC movlw 142 ; WAV-42 movwf PORTB ; put it to the DAC movlw 143 ; WAV-43 movwf PORTB ; put it to the DAC movlw 144 ; WAV-44 movwf PORTB ; put it to the DAC movlw 145 ; WAV-45 movwf PORTB ; put it to the DAC movlw 146 ; WAV-46 movwf PORTB ; put it to the DAC movlw 147 ; WAV-47 movwf PORTB ; put it to the DAC movlw 148 ; WAV-48 movwf PORTB ; put it to the DAC movlw 149 ; WAV-49 movwf PORTB ; put it to the DAC movlw 150 ; WAV-50 movwf PORTB ; put it to the DAC movlw 150 ; WAV-51 movwf PORTB ; put it to the DAC movlw 150 ; WAV-52 movwf PORTB ; put it to the DAC movlw 150 ; WAV-53 movwf PORTB ; put it to the DAC movlw 150 ; WAV-54 movwf PORTB ; put it to the DAC movlw 200 ; WAV-55 movwf PORTB ; put it to the DAC movlw 200 ; WAV-56 movwf PORTB ; put it to the DAC movlw 200 ; WAV-57 movwf PORTB ; put it to the DAC movlw 200 ; WAV-58 movwf PORTB ; put it to the DAC movlw 200 ; WAV-59 movwf PORTB ; put it to the DAC movlw 100 ; WAV-60 movwf PORTB ; put it to the DAC movlw 100 ; WAV-61 movwf PORTB ; put it to the DAC movlw 100 ; WAV-62 movwf PORTB ; put it to the DAC movlw 100 ; WAV-63 movwf PORTB ; put it to the DAC movlw 100 ; WAV-64 movwf PORTB ; put it to the DAC movlw 150 ; WAV-65 movwf PORTB ; put it to the DAC movlw 150 ; WAV-66 movwf PORTB ; put it to the DAC movlw 150 ; WAV-67 movwf PORTB ; put it to the DAC movlw 150 ; WAV-68 movwf PORTB ; put it to the DAC movlw 150 ; WAV-69 movwf PORTB ; put it to the DAC movlw 149 ; WAV-70 movwf PORTB ; put it to the DAC movlw 148 ; WAV-71 movwf PORTB ; put it to the DAC movlw 147 ; WAV-72 movwf PORTB ; put it to the DAC movlw 146 ; WAV-73 movwf PORTB ; put it to the DAC movlw 145 ; WAV-74 movwf PORTB ; put it to the DAC movlw 144 ; WAV-75 movwf PORTB ; put it to the DAC movlw 143 ; WAV-76 movwf PORTB ; put it to the DAC movlw 142 ; WAV-77 movwf PORTB ; put it to the DAC movlw 141 ; WAV-78 movwf PORTB ; put it to the DAC movlw 140 ; WAV-79 movwf PORTB ; put it to the DAC movlw 142 ; WAV-80 movwf PORTB ; put it to the DAC movlw 144 ; WAV-81 movwf PORTB ; put it to the DAC movlw 146 ; WAV-82 movwf PORTB ; put it to the DAC movlw 148 ; WAV-83 movwf PORTB ; put it to the DAC movlw 150 ; WAV-84 movwf PORTB ; put it to the DAC movlw 152 ; WAV-85 movwf PORTB ; put it to the DAC movlw 154 ; WAV-86 movwf PORTB ; put it to the DAC movlw 156 ; WAV-87 movwf PORTB ; put it to the DAC movlw 158 ; WAV-88 movwf PORTB ; put it to the DAC movlw 160 ; WAV-89 movwf PORTB ; put it to the DAC movlw 158 ; WAV-90 movwf PORTB ; put it to the DAC movlw 156 ; WAV-91 movwf PORTB ; put it to the DAC movlw 154 ; WAV-92 movwf PORTB ; put it to the DAC movlw 152 ; WAV-93 movwf PORTB ; put it to the DAC movlw 150 ; WAV-94 movwf PORTB ; put it to the DAC movlw 128 ; WAV-95 movwf PORTB ; put it to the DAC movlw 255 ; WAV-96 movwf PORTB ; put it to the DAC movlw 255 ; WAV-97 movwf PORTB ; put it to the DAC movlw 255 ; WAV-98 movwf PORTB ; put it to the DAC movlw 255 ; WAV-99 movwf PORTB ; put it to the DAC goto l_51 ; and loop waveloop_6 ; loop time is 3uS - DAC inc is 8 ; F=10.41667 KHz movlw 0x80 ; movwf PORTB ; l_61 movlw 1 ; 2 uS delay per increment call us_timer ; plus 1uS code - do the delay movlw 8 ; increment the DAC by 8 addwf PORTB,f ; do it goto l_61 ; and loop waveloop_7 ; loop time is 3uS - DAC inc is 16 ; F=20.8333 KHz movlw 0x80 ; movwf PORTB ; l_71 movlw 1 ; 2 uS delay per increment call us_timer ; plus 1uS code - do the delay movlw 16 ; increment the DAC by 16 addwf PORTB,f ; do it goto l_71 ; and loop waveloop_8 ; loop time is 3uS - DAC inc is 38 ; F=49.4792 KHz movlw 0x80 ; movwf PORTB ; l_81 movlw 1 ; 2 uS delay per increment call us_timer ; plus 1uS code - do the delay movlw 38 ; increment the DAC by 38 addwf PORTB,f ; do it goto l_81 ; and loop waveloop_9 ; loop time is 3uS - DAC inc is 77 ; F=100.2604 KHz movlw 0x80 ; movwf PORTB ; l_91 movlw 1 ; 2 uS delay per increment call us_timer ; plus 1uS code - do the delay movlw 77 ; increment the DAC by 77 addwf PORTB,f ; do it goto l_91 ; and loop ; SquareWave loops waveloop_10 ; 1 MHz SQ wave, duty cycle 2/3 movlw 179 ; Vout is +1V (with OP-AMP) movwf PORTB ; put to the DAC nop nop l_101 comf PORTB,f ; negate the DAC value nop ; pad comf PORTB,f ; and return the DAC to initial value goto l_101 ; and loop waveloop_11 ; 100KHz SQ wave movlw 179 ; Vout is +1V (with OP-AMP) movwf PORTB ; put to the DAC nop nop l_111 comf PORTB,f ; negate the DAC value movlw 3 ; 4 uS delay per increment call us_timer ; plus 1uS delay nop nop nop comf PORTB,f ; and return the DAC to initial value movlw 3 ; 4 uS delay per increment call us_timer ; plus 1uS delay nop goto l_111 ; and loop waveloop_12 ; 10 KHz SQ wave, movlw 179 ; Vout is +1V (with OP-AMP) movwf PORTB ; put to the DAC nop nop l_121 comf PORTB,f ; negate the DAC value movlw 48 ; 49 uS delay per increment call us_timer ; plus 1uS delay nop nop nop comf PORTB,f ; and return the DAC to initial value movlw 48 ; 49 uS delay per increment call us_timer ; plus 1uS delay nop goto l_121 ; and loop waveloop_13 ; 2 KHz SQ wave, movlw 179 ; Vout is +1V (with OP-AMP) movwf PORTB ; put to the DAC nop nop l_131 comf PORTB,f ; negate the DAC value movlw 248 ; 249 uS delay per increment call us_timer ; plus 1uS delay nop nop nop comf PORTB,f ; and return the DAC to initial value movlw 248 ; 249 uS delay per increment call us_timer ; plus 1uS delay nop goto l_131 ; and loop waveloop_14 ; Fast arbitrary waveform generator ; This code is simple in line setting of the DAC values each 1uS for ; a 32 step loop. The values plugged in here are a SINE wave, but may ; be replaced with anything you like. Depending on how much program space ; you have, the number of steps can be anything. Using (say) 100 steps of 1uS ; will give exactly a 10KHz loop. Simply make a table of N values for your ; waveform and edit them into the code. l_141 movlw 128 ; WAV-0 movwf PORTB ; put it to the DAC nop ; nops pad to 1uS per step nop nop movlw 153 ; WAV-1 movwf PORTB ; put it to the DAC nop nop nop movlw 177 ; WAV-2 movwf PORTB ; put it to the DAC nop nop nop movlw 199 ; WAV-3 movwf PORTB ; put it to the DAC nop nop nop movlw 219 ; WAV-4 movwf PORTB ; put it to the DAC nop nop nop movlw 234 ; WAV-5 movwf PORTB ; put it to the DAC nop nop nop movlw 246 ; WAV-6 movwf PORTB ; put it to the DAC nop nop nop movlw 253 ; WAV-7 movwf PORTB ; put it to the DAC nop nop nop movlw 255 ; WAV-8 movwf PORTB ; put it to the DAC nop nop nop movlw 253 ; WAV-9 movwf PORTB ; put it to the DAC nop nop nop movlw 246 ; WAV-10 movwf PORTB ; put it to the DAC nop nop nop movlw 234 ; WAV-11 movwf PORTB ; put it to the DAC nop nop nop movlw 219 ; WAV-12 movwf PORTB ; put it to the DAC nop nop nop movlw 199 ; WAV-13 movwf PORTB ; put it to the DAC nop nop nop movlw 177 ; WAV-14 movwf PORTB ; put it to the DAC nop nop nop movlw 153 ; WAV-15 movwf PORTB ; put it to the DAC nop nop nop movlw 128 ; WAV-16 movwf PORTB ; put it to the DAC nop nop nop movlw 103 ; WAV-17 movwf PORTB ; put it to the DAC nop nop nop movlw 79 ; WAV-18 movwf PORTB ; put it to the DAC nop nop nop movlw 57 ; WAV-19 movwf PORTB ; put it to the DAC nop nop nop movlw 37 ; WAV-20 movwf PORTB ; put it to the DAC nop nop nop movlw 22 ; WAV-21 movwf PORTB ; put it to the DAC nop nop nop movlw 10 ; WAV-22 movwf PORTB ; put it to the DAC nop nop nop movlw 3 ; WAV-23 movwf PORTB ; put it to the DAC nop nop nop movlw 1 ; WAV-24 movwf PORTB ; put it to the DAC nop nop nop movlw 3 ; WAV-25 movwf PORTB ; put it to the DAC nop nop nop movlw 10 ; WAV-26 movwf PORTB ; put it to the DAC nop nop nop movlw 22 ; WAV-27 movwf PORTB ; put it to the DAC nop nop nop movlw 37 ; WAV-28 movwf PORTB ; put it to the DAC nop nop nop movlw 57 ; WAV-29 movwf PORTB ; put it to the DAC nop nop nop movlw 79 ; WAV-30 movwf PORTB ; put it to the DAC nop nop nop movlw 103 ; WAV-31 movwf PORTB ; put it to the DAC nop goto l_141 ; and loop page ;************************************************************************* ; Arbitrary WaveForm Generator - High Precision ;************************************************************************* ; ; DESCRIPTION 32 step arbitrary 8 bit pattern generator ; with sub-hertz period control ; ; This Module uses the values in WAV_16..47 to set output values in PB0..7. ; The position index into this table is the top 5 bits of a running 29 bit ; counter (Phase Accumulator) with a 32 bit Phase increment. A 8uS loop per ; step (125KHz step freq) results in a frequency control of about 0.01 Hz ; REGISTER MAP ; WAV_8,11 29 bit phase index (int.frac 5.24) ; WAV_12,15 32 bit phase increment (int.frac 8.24) ; VMR_16 Output value for step 0 ; VMR_... ; VMR_47 Output value for step 31 ; OPERATION ; ; Top 5 bits of phase accumulator points into 32 byte table and the ; lower 24 bits of the phase accumulator are fractional phase ; Phase increment is full 32 bit - allowing phase steps greater than ; a single table location. If the phase increment is greater than 32 ; it is also possible to step backwards through the table. ; ; While the average frequency of the waveform generated is accurate to < 0.01Hz, ; the sample rate of the generator is 125KHz, which means there may be ; jitter on the waveform of up to 8uS. If this Waveloop is used to generate ; reference signals, a low pass filter after the DAC is recommended. ; ; This WaveLoop operates until the PIC is reset ; HOW TO - change the Wave shape ; ; calculate 32 points in your waveform, remembering that 00 corresponds to ; the most negative output of the DAC and ff the most positive output. ; Alter the code in "init_wav" to your calculated values. In the case ; where you wish to use this loop to generate a logic sequence, make a ; Logic State table of 32 values and edit these into the code. ; The 32 values will be repeated indefinitely, at the rate determined by the ; Phase Increment register. ; HOW TO - set the loop frequency ; ; The control registers for this WaveLoop are the Phase accumulator and ; the Phase Increment register. Both of these registers are 32 bits (4 bytes) ; in the form of integer.fraction binary numbers. This means that the msb (most ; signifigant byte) represents a integer number of steps through the 32 byte ; wave table, and the other 3 bytes represent a 24 bit binary fraction of a step. ; The Phase accumulator is usually set at 0.000 - as the initial value is of ; no interest. For a logic sequencer this may not be true and it should be ; set accordingly. ; The Phase Increment parameter represents the exact number of steps (a.bcd) ; that the phase accumulator is advanced each loop (8uS). The value to advance ; 1 step per loop is 1.000. This will result in all 32 table entries being output ; in 32 x 8uS (256uS or F=3.90625KHz) ; In general, this means that the frequency of the waveform will be calculated ; ; F = 3906.25 x Phase_Inc Hz ; ; OR ; ; Phase_Inc = F / 3906.25 ; ; To make a 100Hz waveform, we would calculate the Phase Increment as:- ; ; Phase_Inc = 100/3906.25 ; = 0.0256 ; ; Convert this to a binary number - 16,777,216 x 0.0256 = 429497 ; Which is 0.068db9 - the binary (int.frac) corresponding to 0.0256 ; What will happen here is that about every 39 loops, the Phase accumulator ; will advance by one step. ; ; To make a 1000Hz waveform, we would calculate the Phase Increment as:- ; ; Phase_Inc = 1000/3906.25 ; = 0.256 ; ; Convert this to a binary number - 16,777,216 x 0.0256 = 4,294,967 ; Which is 00.418937 - the binary (int.frac) corresponding to 0.256 ; What will happen here is that about every 4 loops, the Phase accumulator ; will advance by one step. ; HOW TO - make a very slow logic sequencer ; ; If the Phase Increment registers are set to 00.000001 (hex), this will mean that ; each step through the 32 entry table will require 2^24 (16,777,216) 8uS loops ; to execute. This is 134.2 seconds - quite a long time. At this rate it will ; take just over an hour to step through all 32 table entries. ; APPLICATIONS ; ; counter, pattern generator ; with DAC arbitrary waveform generator ; 32 step oscillator, 8 uS step ; frequency synth waveloop_15 ; initialize the 32 registers with ; the wave table (sine wave) ; put in the values of a full scale sine wave init_wav movlw 128 ; WAV-0 movwf WAV_16 ; put it in RAM table movlw 153 ; WAV-1 movwf WAV_17 ; put it in RAM table movlw 177 ; WAV-2 movwf WAV_18 ; put it in RAM table movlw 199 ; WAV-3 movwf WAV_19 ; put it in RAM table movlw 219 ; WAV-4 movwf WAV_20 ; put it in RAM table movlw 234 ; WAV-5 movwf WAV_21 ; put it in RAM table movlw 246 ; WAV-6 movwf WAV_22 ; put it in RAM table movlw 253 ; WAV-7 movwf WAV_23 ; put it in RAM table movlw 255 ; WAV-8 movwf WAV_24 ; put it in RAM table movlw 253 ; WAV-9 movwf WAV_25 ; put it in RAM table movlw 246 ; WAV-10 movwf WAV_26 ; put it in RAM table movlw 234 ; WAV-11 movwf WAV_27 ; put it in RAM table movlw 219 ; WAV-12 movwf WAV_28 ; put it in RAM table movlw 199 ; WAV-13 movwf WAV_29 ; put it in RAM table movlw 177 ; WAV-14 movwf WAV_30 ; put it in RAM table movlw 153 ; WAV-15 movwf WAV_31 ; put it in RAM table movlw 128 ; WAV-16 movwf WAV_32 ; put it in RAM table movlw 103 ; WAV-17 movwf WAV_33 ; put it in RAM table movlw 79 ; WAV-18 movwf WAV_34 ; put it in RAM table movlw 57 ; WAV-19 movwf WAV_35 ; put it in RAM table movlw 37 ; WAV-20 movwf WAV_36 ; put it in RAM table movlw 22 ; WAV-21 movwf WAV_37 ; put it in RAM table movlw 10 ; WAV-22 movwf WAV_38 ; put it in RAM table movlw 3 ; WAV-23 movwf WAV_39 ; put it in RAM table movlw 1 ; WAV-24 movwf WAV_40 ; put it in RAM table movlw 3 ; WAV-25 movwf WAV_41 ; put it in RAM table movlw 10 ; WAV-26 movwf WAV_42 ; put it in RAM table movlw 22 ; WAV-27 movwf WAV_43 ; put it in RAM table movlw 37 ; WAV-28 movwf WAV_44 ; put it in RAM table movlw 57 ; WAV-29 movwf WAV_45 ; put it in RAM table movlw 79 ; WAV-30 movwf WAV_46 ; put it in RAM table movlw 103 ; WAV-31 movwf WAV_47 ; put it in RAM table ; initialize the phase accumulator and the phase offset movlw 0x00 ; Phase Accumulator msb movwf WAV_11 ; put in register movlw 0x00 ; Phase Accumulator movwf WAV_10 ; put in register movlw 0x00 ; Phase Accumulator movwf WAV_9 ; put in register movlw 0x00 ; Phase Accumulator lsb movwf WAV_8 ; put in register ; put in here the example values to give a 1KHz wave movlw 0x00 ; Phase increment msb movwf WAV_15 ; put in register movlw 0x41 ; Phase increment movwf WAV_14 ; put in register movlw 0x89 ; Phase increment movwf WAV_13 ; put in register movlw 0x37 ; Phase increment lsb movwf WAV_12 ; put in register ; all the initial values of the registers are now set. ; this is the main loop which takes 8uS to complete. l_15_1 movlw 0x1f ; mask for 5 bits of phase andwf WAV_11,W ; get the 5 msbs into W addlw WAV_16 ; offset from VMR-16 movwf FSR ; put in reg pointer movf INDF,W ; put the reg in W movwf PORTB ; that is it! ; next step is to increment the phase ; 32 bit addition for phase + increment -> phase movf WAV_12,W ; get the lsb of increment addwf WAV_8,F ; add it to the lsb of phase clrz ; explicitly clear Z bit skpnc ; did we get a carry? setz ; yes - mirror it in Z bit ; ripple it up the 3 higher bytes skpnz ; incf WAV_9,F ; skpnz ; incf WAV_10,F ; skpnz ; incf WAV_11,F ; movf WAV_13,W ; get next byte addwf WAV_9,F ; add to phase clrz ; explicitly clear Z bit skpnc ; carry? setz ; yes - mirror it in Z bit ; ripple it up 2 bytes skpnz ; incf WAV_10,F ; skpnz ; incf WAV_11,F ; movf WAV_14,W ; get the next byte addwf WAV_10,F ; add to phase clrz ; explicitly clear Z bit skpnc ; carry? setz ; yes - mirror it in Z bit ; ripple it up last byte skpnz ; incf WAV_11,F ; movf WAV_15,W ; get the MSB addwf WAV_11,F ; and put in phase ; we don't care about C nop nop nop goto l_15_1 ; loop again ; loop is 40 instructions (8uS) page ;*********************************************************************** ; Main Jump Table for WaveLoops - RANGE f0 -> fF ;*********************************************************************** org 0x7f0 ; locate table up here at 3f0 -> 3ff wav_00 goto waveloop_0 ; wav_01 goto waveloop_1 ; wav_02 goto waveloop_2 ; wav_03 goto waveloop_3 ; wav_04 goto waveloop_4 ; wav_05 goto waveloop_5 ; wav_06 goto waveloop_6 ; wav_07 goto waveloop_7 ; wav_08 goto waveloop_8 ; wav_09 goto waveloop_9 ; wav_0a goto waveloop_10 ; wav_0b goto waveloop_11 ; wav_0c goto waveloop_12 ; wav_0d goto waveloop_13 ; wav_0e goto waveloop_14 ; wav_0f goto waveloop_15 ; END