Shop OBEX P1 Docs P2 Docs Learn Events
Continuous DDS updating — Parallax Forums

Continuous DDS updating

dmwilson86dmwilson86 Posts: 27
edited 2011-04-14 14:33 in Propeller 1
Okay, so our keyboard synthesizer project is coming along well, but we have a few bugs to work out. The issue now is the updating the frequencies being thrown out to the dac. Here is a screenshot of the problem:
TEK00002.gif

Essentially everytime the cog is restarted to start playing the updated list of frequencies, it has to reset. This is causing a pulsing sound (and in the output waveform). Here is the top object file:
con
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000
obj
  sinsynth : "sintabsynth"
  sawsynth : "sawtabsynth"
  trisynth : "triangletabsynth"
  squaresynth:"squaretabsynth"
  keyReader:"keyReader"
  DDS      : "DDS_PASM"
  Debug    : "FullDuplexSerial"
var     
  long playFreqs[6]
  long playPress[6]
  byte t1
pub main
  Debug.start(31,30,0,57600)               
  keyReader.start(@playFreqs, @playPress)
  repeat
    waitcnt(clkfreq/20 + cnt)
    DDS.start(playFreqs[0]*10000/322,playFreqs[1]*10000/322,playFreqs[2]*10000/322,playFreqs[3]*10000/322,playFreqs[4]*10000/322,playFreqs[5]*10000/322)
The playFreq calculations for each parameter are there to calculate the frequency tuning ratio for the following code:
VAR
  long  cog                                      'cog id
PUB start(M1,M2,M3,M4,M5,M6) : okay                              'M is the tuning word
  stop                                           'Stop DDS if it is running, frees a cog
  M1_ := M1                                        'Assign passed variable (tuning word)
  M2_ := M2
  M3_ := M3
  M4_ := M4
  M5_ := M5
  M6_ := M6
  okay := cog := cognew(@entry,0)                'Start DDS, uses a cog.
PUB stop
  if cog                                         'If cog is running
    cogstop(cog~)                                'Stop DDS, frees a cog
        
DAT
                         org      0
  entry                    
  Sine          long $80,$83,$86,$89,$8C,$8F,$92,$95,$98,$9C,$9F,$A2,$A5,$A8,$AB,$AE
                long $B0,$B3,$B6,$B9,$BC,$BF,$C1,$C4,$C7,$C9,$CC,$CE,$D1,$D3,$D5,$D8
                long $DA,$DC,$DE,$E0,$E2,$E4,$E6,$E8,$EA,$EC,$ED,$EF,$F0,$F2,$F3,$F5
                long $F6,$F7,$F8,$F9,$FA,$FB,$FC,$FC,$FD,$FE,$FE,$FF,$FF,$FF,$FF,$FF
                long $FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$FD,$FC,$FC,$FB,$FA,$F9,$F8,$F7
                long $F6,$F5,$F3,$F2,$F0,$EF,$ED,$EC,$EA,$E8,$E6,$E4,$E2,$E0,$DE,$DC
                long $DA,$D8,$D5,$D3,$D1,$CE,$CC,$C9,$C7,$C4,$C1,$BF,$BC,$B9,$B6,$B3
                long $B0,$AE,$AB,$A8,$A5,$A2,$9F,$9C,$98,$95,$92,$8F,$8C,$89,$86,$83
                long $80,$7C,$79,$76,$73,$70,$6D,$6A,$67,$63,$60,$5D,$5A,$57,$54,$51
                long $4F,$4C,$49,$46,$43,$40,$3E,$3B,$38,$36,$33,$31,$2E,$2C,$2A,$27
                long $25,$23,$21,$1F,$1D,$1B,$19,$17,$15,$13,$12,$10,$0F,$0D,$0C,$0A
                long $09,$08,$07,$06,$05,$04,$03,$03,$02,$01,$01,$00,$00,$00,$00,$00
                long $00,$00,$00,$00,$00,$00,$01,$01,$02,$03,$03,$04,$05,$06,$07,$08
                long $09,$0A,$0C,$0D,$0F,$10,$12,$13,$15,$17,$19,$1B,$1D,$1F,$21,$23
                long $25,$27,$2A,$2C,$2E,$31,$33,$36,$38,$3B,$3E,$40,$43,$46,$49,$4C
                long $4F,$51,$54,$57,$5A,$5D,$60,$63,$67,$6A,$6D,$70,$73,$76,$79,$7C
                mov      dira,    PinMsk         'LSB to PA0, LSB to PA7
  :loop         add      Acc1,     M1_   wz          'M $1FF max if literal with #$xxx  
                ror      Acc1,     #16            'Postion index 
                movs     :inline1, Acc1            'Store 9-bit index
                andn     :inline1, #%1_00000000   'Clamp to 8-bits
                rol      Acc1,     #16            'Restore accumulator
  :inline1     if_nz mov      outa,    0-0            'Get long value from table 
                add      Acc2,     M2_  wz
                ror      Acc2,     #16
                movs     :inline2, Acc2            'Store 9-bit index
                andn     :inline2, #%1_00000000   'Clamp to 8-bits
                rol      Acc2,     #16            'Restore accumulator 
  :inline2      if_nz mov      outa,    0-0            'Get long value from table
                add      Acc3,     M3_  wz
                ror      Acc3,     #16
                movs     :inline3, Acc3            'Store 9-bit index
                andn     :inline3, #%1_00000000   'Clamp to 8-bits
                rol      Acc3,     #16            'Restore accumulator
  :inline3 if_nz mov      outa,    0-0
                add      Acc4,     M4_  wz
                ror      Acc4,     #16
                movs     :inline4, Acc4            'Store 9-bit index
                andn     :inline4, #%1_00000000   'Clamp to 8-bits
                rol      Acc4,     #16            'Restore accumulator  
  :inline4     if_nz mov      outa,    0-0
                add      Acc5,     M5_  wz
                ror      Acc5,     #16
                movs     :inline5, Acc5            'Store 9-bit index
                andn     :inline5, #%1_00000000   'Clamp to 8-bits
                rol      Acc5,     #16            'Restore accumulator    
  :inline5     if_nz mov      outa,    0-0
                add      Acc6,     M6_  wz
                ror      Acc6,     #16
                movs     :inline6, Acc6            'Store 9-bit index
                andn     :inline6, #%1_00000000   'Clamp to 8-bits
                rol      Acc6,     #16            'Restore accumulator   
  :inline6      if_nz mov      outa,    0-0    
                jmp      #:loop                  'Loop again
  PinMsk        long     $FF                     '8-bit DAC, LSB on PA0, MSB on PA7
  M1_            long     0                       'Tuning word var init
  M2_            long     0
  M3_            long     0
  M4_            long     0
  M5_            long     0
  M6_            long     0
  Acc1           long     0                       'Accumulator var init
  Acc2           long     0
  Acc3           long     0
  Acc4           long     0
  Acc5           long     0
  Acc6           long     0  
  
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                   TERMS OF USE: MIT License                                                  │                                                            
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    │ 
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions:                                                                   │
│                                                                                                                              │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│                                                                                                                              │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}
Essentially, I need to actively update the frequencies to be produced actively, without stopping and starting the cog again. Any suggestions?
640 x 480 - 22K

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-04-13 17:53
    Have a look at the most recent postings in the [thread=121470]A Sine Wave DDS in PASM - Comments?[/thread] thread. It shows hub updates for the tuning word. HTH
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-04-13 18:51
    kuroneko wrote: »
    Have a look at the most recent postings in the [thread=121470]A Sine Wave DDS in PASM - Comments?[/thread] thread. It shows hub updates for the tuning word. HTH
    Nice, thanks. Time for a little down and dirty study on that.
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-04-14 14:26
    Alright, I understand and am implementing the code for one channel with continuous DDS updating. It works nicely, but when I try and interleave two (or more) channels together everything falls apart. I've been trying all afternoon but I can't seem to figure it out. I realize timing is important, but I guess I need some insight into how to get that right. Pretty tricky stuff, hoping it's doable, here's the code:
    VAR
      long  cog                                      'cog id
      long FreqControl1
      long FreqControl2
      long FreqControl3
      long FreqControl4
      long FreqControl5
      long FreqControl6
    PUB start(M1,M2, M3, M4, M5, M6) : okay                              'M is the tuning word
      stop
      FreqControl1 := $41893 ''$E560                   'Stop DDS if it is running, frees a cog
      FreqControl2 := $41893
      FreqControl3 := $41893
      FreqControl4 := $41893
      FreqControl5 := $41893
      FreqControl6 := $41893
      M1_ := M1                                       'Assign passed variable (tuning word)
      M2_ := M2
      M3_ := M3
      M4_ := M4
      M5_ := M5
      M6_ := M6                                         
      okay := cog := cognew(@entry,@FreqControl1)      'Start DDS, uses a cog.
    PUB stop
      if cog                                         'If cog is running
        cogstop(cog~)                                'Stop DDS, frees a cog
    PUB ChangeFreq(NewFreq1, NewFreq2, NewFreq3,NewFreq4,NewFreq5,NewFreq6)
      FreqControl1 := NewFreq1
      FreqControl2 := NewFreq2
      FreqControl3 := NewFreq3
      FreqControl4 := NewFreq4
      FreqControl5 := NewFreq5
      FreqControl6 := NewFreq6  
    DAT
                             org      0
      entry
      Sine          long $80,$83,$86,$89,$8C,$8F,$92,$95,$98,$9C,$9F,$A2,$A5,$A8,$AB,$AE
                    long $B0,$B3,$B6,$B9,$BC,$BF,$C1,$C4,$C7,$C9,$CC,$CE,$D1,$D3,$D5,$D8
                    long $DA,$DC,$DE,$E0,$E2,$E4,$E6,$E8,$EA,$EC,$ED,$EF,$F0,$F2,$F3,$F5
                    long $F6,$F7,$F8,$F9,$FA,$FB,$FC,$FC,$FD,$FE,$FE,$FF,$FF,$FF,$FF,$FF
                    long $FF,$FF,$FF,$FF,$FF,$FF,$FE,$FE,$FD,$FC,$FC,$FB,$FA,$F9,$F8,$F7
                    long $F6,$F5,$F3,$F2,$F0,$EF,$ED,$EC,$EA,$E8,$E6,$E4,$E2,$E0,$DE,$DC
                    long $DA,$D8,$D5,$D3,$D1,$CE,$CC,$C9,$C7,$C4,$C1,$BF,$BC,$B9,$B6,$B3
                    long $B0,$AE,$AB,$A8,$A5,$A2,$9F,$9C,$98,$95,$92,$8F,$8C,$89,$86,$83
                    long $80,$7C,$79,$76,$73,$70,$6D,$6A,$67,$63,$60,$5D,$5A,$57,$54,$51
                    long $4F,$4C,$49,$46,$43,$40,$3E,$3B,$38,$36,$33,$31,$2E,$2C,$2A,$27
                    long $25,$23,$21,$1F,$1D,$1B,$19,$17,$15,$13,$12,$10,$0F,$0D,$0C,$0A
                    long $09,$08,$07,$06,$05,$04,$03,$03,$02,$01,$01,$00,$00,$00,$00,$00
                    long $00,$00,$00,$00,$00,$00,$01,$01,$02,$03,$03,$04,$05,$06,$07,$08
                    long $09,$0A,$0C,$0D,$0F,$10,$12,$13,$15,$17,$19,$1B,$1D,$1F,$21,$23
                    long $25,$27,$2A,$2C,$2E,$31,$33,$36,$38,$3B,$3E,$40,$43,$46,$49,$4C
                    long $4F,$51,$54,$57,$5A,$5D,$60,$63,$67,$6A,$6D,$70,$73,$76,$79,$7C
                    mov      dira,    PinMsk         'LSB to PA0, LSB to PA7
      :loop         rdlong   M1_, par                  'Get Freq Control Value   
                    mov      CtrlPtr, par   
                    add      Acc1,     M1_  wz           'M $1FF max if literal with #$xxx
                    ror      Acc1,     #16            'Postion index
                    movs     :inline1, Acc1            'Store 9-bit index
                    andn     :inline1, #%1_00000000   'Clamp to 8-bits
                    rol      Acc1,     #16            'Restore accumulator
      :inline1      mov      outa,    0-0            'Get long value from table
                    add      CtrlPtr, #32
                    rdlong   M2_,CtrlPtr                  'Get Freq Control Value
                    add      Acc2,     M2_   wz          'M $1FF max if literal with #$xxx
                    ror      Acc2,     #16            'Postion index
                    movs     :inline2, Acc2            'Store 9-bit index
                    andn     :inline2, #%1_00000000   'Clamp to 8-bits
                    rol      Acc2,     #16            'Restore accumulator
      :inline2    if_nz  mov      outa,    0-0            'Get long value from table
              {{     add      CtrlPtr, #32
                    rdlong   M3_,CtrlPtr                  'Get Freq Control Value
                    add      Acc3,     M3_  wz           'M $1FF max if literal with #$xxx
                    ror      Acc3,     #16            'Postion index
                    movs     :inline3, Acc3            'Store 9-bit index
                    andn     :inline3, #%1_00000000   'Clamp to 8-bits
                    rol      Acc3,     #16            'Restore accumulator
      :inline3     if_nz mov      outa,    0-0            'Get long value from table
              {{      add      CtrlPtr, #32
                    rdlong   M4_,CtrlPtr                  'Get Freq Control Value
                    add      Acc4,     M4_             'M $1FF max if literal with #$xxx
                    ror      Acc4,     #16            'Postion index
                    movs     :inline4, Acc4            'Store 9-bit index
                    andn     :inline4, #%1_00000000   'Clamp to 8-bits
                    rol      Acc4,     #16            'Restore accumulator
      :inline4      mov      outa,    0-0            'Get long value from table
                    add      CtrlPtr, #32
                    rdlong   M5_,CtrlPtr                 'Get Freq Control Value
                    add      Acc5,     M5_             'M $1FF max if literal with #$xxx
                    ror      Acc5,     #16            'Postion index
                    movs     :inline5, Acc5            'Store 9-bit index
                    andn     :inline5, #%1_00000000   'Clamp to 8-bits
                    rol      Acc5,     #16            'Restore accumulator
      :inline5      mov      outa,    0-0            'Get long value from table
                    add      CtrlPtr, #32
                    rdlong   M6_,CtrlPtr                  'Get Freq Control Value
                    add      Acc6,     M6_             'M $1FF max if literal with #$xxx
                    ror      Acc6,     #16            'Postion index
                    movs     :inline6, Acc6            'Store 9-bit index
                    andn     :inline6, #%1_00000000   'Clamp to 8-bits
                    rol      Acc6,     #16            'Restore accumulator
      :inline6       mov      outa,    0-0 }}           'Get long value from table
                    jmp      #:loop                 'Loop again
    
  • Heater.Heater. Posts: 21,230
    edited 2011-04-14 14:33
    Those "add CtrlPtr, #32" satements don't look right to me.
    Your FreqControlx values are LONGs.
    So they are separated by 4 bytes.
    So I think you should be using "add CtrlPtr, #4" instead.
Sign In or Register to comment.