Shop OBEX P1 Docs P2 Docs Learn Events
Parallel out sine wave from custom sine table — Parallax Forums

Parallel out sine wave from custom sine table

dmwilson86dmwilson86 Posts: 27
edited 2011-03-26 19:35 in Propeller 1
Okay, so I've been trying to output a discrete signal to a resistor dac on pins p0-p8 for three days to no avail. I'm hoping someone can tell me my fatal mistakes, I'm desperate. Thanks.
con
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000
obj
var
  long cog1
pub main
   cog1:=cognew(@sinwave, 0) +1
   

dat
org
sinwave
              mov DIRA, #$FF
              mov t1, #0
              mov sin, #0
              mov acc, #0
              mov ptr, #sintab
:loop         add ptr, #128
              movs :set, ptr
:set          mov outa, 0-0  
              testn acc,#255 wz
              if_z mov acc,#0
              if_z mov ptr, #sintab
              if_nz add acc, #1
              if_nz add ptr, #1
              jmp #:loop

              
sin           long 0
t1            long 0
acc           long 0
ptr           long 0
sintab  long 128, 132, 135, 138, 141, 144, 147, 150, 153, 157, 160, 163, 166, 169, 172, 175, 177, 180, 183, 186
long 189, 192, 194, 197, 200, 202, 205, 207, 210, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233
long 235, 237, 238, 240, 241, 243, 244, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 255, 255, 256
long 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 253, 253, 252, 251, 250, 249, 248
long 247, 246, 244, 243, 241, 240, 238, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 214, 212
long 210, 207, 205, 202, 200, 197, 194, 192, 189, 186, 183, 180, 177, 175, 172, 169, 166, 163, 160, 157
long 153, 150, 147, 144, 141, 138, 135, 132, 129, 125, 122, 119, 116, 113, 110, 107, 104, 100, 97, 94
long 91, 88, 85, 82, 80, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40
long 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7
long 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2
long 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 26, 28
long 30, 32, 34, 36, 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77
long 80, 82, 85, 88, 91, 94, 97, 100, 104, 107, 110, 113, 116, 119, 122, 125

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 16:57
    Why is the add ptr, #128 inside the loop? Cog registers are addressed from 0..511 so adding 128 at this rate seems wrong. Also, code modifications need at least one instruction between modification and executing the (modified) instruction. It may well be intended (delayed effect) but I mention it just in case.

    Also, the table only has 236 entries. As for testn, this will do a binary AND of !255 == $FFFFFF00 against acc. As acc is 0 it will always result in the Z flag being set which keeps acc at 0. Maybe you meant to use cmp & Co (or do the reset for if_nz)?
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 17:13
    Why is the add ptr, #128 inside the loop?
    Right. That was just there for me to test and see if I could output a value in the middle of the custom sin table (without the loop).
    Also, the table only has 236 entries.
    Unless I'm completely burnt out I think there are 256. 12 lines of 20 entries each=240, plus the last line with 16 entries = 256
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 17:18
    Re: table length, my mistake. I forgot to copy the first line.
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 17:25
    The proptool tells me that a label after the table will end up at $EC (if I just put the table into a DAT section). So some lines are missing?
    Maybe a carriage return after the label 'sintab' will fix that since there are exactly 20 unnaccounted for? Also, how did you check that with the proptool?
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 17:27
    dmwilson86 wrote: »
    Why is it doing the and with $FFFFFF00 and not with acc? I think I'm misunderstading something (what do you mean by 'against acc').
    What I meant is it performs acc & $FFFFFF00 and just affects the flags. I think the idea is to spot when bit 8 goes high (256). For this to work you'd need to change the reset condition to if_nz as everything from 0 to 255 will result in Z being set.
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 17:29
    What I meant is it performs acc & $FFFFFF00 and just affects the flags. I think the idea is to spot when bit 8 goes high (256). For this to work you'd need to change the reset condition to if_nz as everything from 0 to 255 will result in Z being set.
    Gotcha, thanks for that
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 17:29
    dmwilson86 wrote: »
    Maybe a carriage return after the label 'sintab' will fix that since there are exactly 20 unnaccounted for? Also, how did you check that with the proptool?
    Spotted my mistake. See post edit.

    As for checking, add labels at the appropriate locations, press F9 and place the cursor on the label you're interested in. The status line will give you info as to object location and cog offset.
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 18:21
    Okay! Now I'm getting somewhere. Thanks kuroneko! I've got a sine wave coming out of my resistor dac now, except it has a break to zero once/period. Any ideas why?
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 18:27
    You'll need at least one instruction between movs :set, ptr and mov outa, 0-0 (see first reply). Just put a nop in there. This can be replaced later with something useful e.g. you could move the testn instruction into this slot. Can you post your updated code to make sure we're on the same page?
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 18:35
    Here is the updated code:
    con
      _CLKMODE = XTAL1 + PLL16X
      _XINFREQ = 5_000_000 
    obj
    var
      long cog1
    pub main
       cog1:=cognew(@sinwave, 0) +1
       
    
    dat
    org
    sinwave
                  mov DIRA, #$FF
                  mov t1, #0  
                  mov acc, #0
                  mov ptr, #sintab
                  add ptr, #1
    :loop         movs :set, ptr  
    :set          mov outa, 0-0  
                  testn acc,top wz
                  if_z jmp #:accum
    :reset        mov acc,#0
                  mov ptr, #sintab
                  jmp #:loop
    :accum        add acc, #1 
                  add ptr, #1 
                  jmp #:loop
    
                         
    t1            long 0
    acc           long 0
    ptr           long 0
    top           long 255
    sintab  long 128, 132, 135, 138, 141, 144, 147, 150, 153, 157, 160, 163, 166, 169, 172, 175, 177, 180, 183, 186
    long 189, 192, 194, 197, 200, 202, 205, 207, 210, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233
    long 235, 237, 238, 240, 241, 243, 244, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 255, 255, 256
    long 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 253, 253, 252, 251, 250, 249, 248
    long 247, 246, 244, 243, 241, 240, 238, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 214, 212
    long 210, 207, 205, 202, 200, 197, 194, 192, 189, 186, 183, 180, 177, 175, 172, 169, 166, 163, 160, 157
    long 153, 150, 147, 144, 141, 138, 135, 132, 129, 125, 122, 119, 116, 113, 110, 107, 104, 100, 97, 94
    long 91, 88, 85, 82, 80, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40
    long 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7
    long 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2
    long 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 26, 28
    long 30, 32, 34, 36, 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77
    long 80, 82, 85, 88, 91, 94, 97, 100, 104, 107, 110, 113, 116, 119, 122, 125,128
    
    I tried to use the nop between the two instructions, and it seemed to just slow down the frequency. It didn't have any effect on the break to zero.
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 18:49
    screenshot.gif
    Here is what I'm getting right now. I'm not sure whether the flaw in triggering is due to a constant shifting of phase or from the oscilloscope not being able to trigger properly.
    640 x 480 - 21K
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 18:54
    It looks like an off by 1 issue in your index handling. Try this:
    CON
      _clkmode = XTAL1 + PLL16X
      _xinfreq = 5_000_000 
    
    PUB main
    
      cognew(@sinwave, 0)
    
    DAT             org     0
    
    sinwave         mov     dira, #$FF
    :reset          mov     ptr, #sintab
    :loop           movs    :set, ptr
                    add     ptr, #1
    :set            mov     outa, 0-0
                    cmp     ptr, #sintab_end wz
            if_e    jmp     #:reset                 ' reached end of table
                    jmp     #:loop
    
    ptr             long 0
    
    sintab          long 128, 132, 135, 138, 141, 144, 147, 150, 153, 157, 160, 163, 166, 169, 172, 175, 177, 180, 183, 186
                    long 189, 192, 194, 197, 200, 202, 205, 207, 210, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233
                    long 235, 237, 238, 240, 241, 243, 244, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 255, 255, 256
                    long 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 253, 253, 252, 251, 250, 249, 248
                    long 247, 246, 244, 243, 241, 240, 238, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 214, 212
                    long 210, 207, 205, 202, 200, 197, 194, 192, 189, 186, 183, 180, 177, 175, 172, 169, 166, 163, 160, 157
                    long 153, 150, 147, 144, 141, 138, 135, 132, 129, 125, 122, 119, 116, 113, 110, 107, 104, 100, 97, 94
                    long 91, 88, 85, 82, 80, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40
                    long 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7
                    long 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2
                    long 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 26, 28
                    long 30, 32, 34, 36, 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77
                    long 80, 82, 85, 88, 91, 94, 97, 100, 104, 107, 110, 113, 116, 119, 122, 125
    sintab_end
    
    DAT
    
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 18:57
    Wow, you really simplified all that. Unfortunately the same thing is still happening.
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 19:13
    dmwilson86 wrote: »
    Wow, you really simplified all that. Unfortunately the same thing is still happening.
    OK, yes, your table contains 9bit values but your dira mask only enables 8 of them. Just change it to mov dira, #$1FF. I was confused earlier since you mentioned pins 0-8 but only used a byte mask. Therefore I assumed that the table only holds byte values. My mistake.
  • martinhmartinh Posts: 58
    edited 2011-03-26 19:14
    You say you want to output to P0-P8, are you sure that your mov DIRA, #$FF is correct, it looks to me as if this should be $1FF.

    Edit: @kuroneko
    You have beaten me by a few seconds :lol:
  • Heater.Heater. Posts: 21,230
    edited 2011-03-26 19:17
    dmwilson86 and kuroneko,

    Your algorithms are too complicated, what's with all this checking for sin_tab_end?

    Why not use the simple Direct Digital Synthesis (DDS) technique?

    1) Have sine table of 256 longs.
    2) Have 32 bit counter, call it "phase" that maintains he current position in the wave.
    3) Use only the top 8 bits of phase to index the sin table for the current sample value.
    4) Add a small amount "delta" to the phase value on every iteration.
    5) Changing the value of delta changes your frequency with a very high resolution.

    With this there is no need to check for end of table, the 8 bits of phase used to index the table will just wrap around to the table as required.

    If you arrange for the table to start at location zero in your code you save a few instructions as you don't need to add any base offset address of the table when you access it.

    A guy called Jesper did this in 6 lines of AVR code in his miniDDS project: www.myplace.nu/avr/minidds/index.htm
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 19:20
    Heater. wrote: »
    Your algorithms are too complicated, what's with all this checking for sin_tab_end?
    They do work. That's all what's required initially. For improvements see this thread [thread=121470]A Sine Wave DDS in PASM - Comments?[/thread].
  • Heater.Heater. Posts: 21,230
    edited 2011-03-26 19:24
    kuroneko,

    I know you are not normally happy with just "it works" :)
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 19:30
    @Heater: mumblemumbletruemumble. We don't know nothing about the OPs experience. So isn't it better to solve the immediate problem first before swamping him with black magic? :)
  • dmwilson86dmwilson86 Posts: 27
    edited 2011-03-26 19:35
    OK, yes, your table contains 9bit values but your dira mask only enables 8 of them. Just change it to mov dira, #$1FF.
    Yes! This was the problem...I wrongly stated pins 'p0-p8' but I meant p0-p7. So I used the updated code with 'dira,#$1FF', and added another resistor to my dac, and it worked great! Thanks for all the help. I think definitely need to approach Heater's suggestion since I need to interleave more than one channel to the dac, but all the code examples and the help here have really helped me understand pasm much better. Thanks everyone!
Sign In or Register to comment.