WavePOD Firmware

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