Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

Problem with DDS

Problem with DDS

2003-12-03 by Leon Heller

I'm using the following code for software direct digital waveform synthesis:

int main(void)
{
  unsigned int i;
  unsigned long int acc, adder;
  unsigned int ptr, temp;

  initPLL();
  MAMCR = 0;
  MAMTIM = 5;
  MAMCR = 2;
  VPBDIV = 0x01;
  portInit();
  //main loop
  //add value to accumulator
  //load byte from current table
  //output byte to port
  //repeat

  adder = 2000;               //set up adder
  acc = 0;                    //clear accumulator
  while (1)
  {
    acc = acc + adder;      //update phase accumulator
    ptr = (acc &= 0xFF);    //pointer into table
    IOSET = square[ptr] << 8;//output byte to port
    IOCLR = ~(square[ptr] << 8);
  }
  return 0;
}

but I can't get an equal mark-space ratio out of it for a square wave, and
sine waves are completely screwed up.

The following code for an AVR works very well:

; main loop
;
; r28,r29,r30 is the phase accumulator
;   r24,r25,r26 is the adder value determining frequency
;
;  add value to accumulator
; load byte from current table in ROM
; output byte to port
; repeat
;
LOOP1:
  add  r28,r24   ; 1
  adc  r29,r25   ; 1
  adc  r30,r26   ; 1
  lpm      ; 3
  out  PORTB,r0  ; 1
  rjmp LOOP1   ; 2 => 9 cycles

I'm using the same AD557 8-bit DAC and the same look-up tables. I'm
obviously doing something silly, but I can't see what it is. Can anyone
help?

Leon
--
Leon Heller, G1HSM
Email: aqzf13@...
http://www.geocities.com/leon_heller

Re: [lpc2100] Problem with DDS

2003-12-03 by otc_friend

Hi Leon -
I don't step deep into it but as you using variables greater 8 bits what's
about little-endian/big-endian confusion, maybe?
Regards -
Henry

-----Urspr\ufffdngliche Nachricht-----
Von: Leon Heller <leon_heller@...>
An: lpc2100@yahoogroups.com <lpc2100@yahoogroups.com>
Datum: Mittwoch, 3. Dezember 2003 11:46
Betreff: [lpc2100] Problem with DDS


>I'm using the following code for software direct digital waveform
synthesis:
Show quoted textHide quoted text
>
>int main(void)
>{
>  unsigned int i;
>  unsigned long int acc, adder;
>  unsigned int ptr, temp;
>
>  initPLL();
>  MAMCR = 0;
>  MAMTIM = 5;
>  MAMCR = 2;
>  VPBDIV = 0x01;
>  portInit();
>  //main loop
>  //add value to accumulator
>  //load byte from current table
>  //output byte to port
>  //repeat
>
>  adder = 2000;               //set up adder
>  acc = 0;                    //clear accumulator
>  while (1)
>  {
>    acc = acc + adder;      //update phase accumulator
>    ptr = (acc &= 0xFF);    //pointer into table
>    IOSET = square[ptr] << 8;//output byte to port
>    IOCLR = ~(square[ptr] << 8);
>  }
>  return 0;
>}
>
>but I can't get an equal mark-space ratio out of it for a square wave, and
>sine waves are completely screwed up.
>
>The following code for an AVR works very well:
>
>; main loop
>;
>; r28,r29,r30 is the phase accumulator
>;   r24,r25,r26 is the adder value determining frequency
>;
>;  add value to accumulator
>; load byte from current table in ROM
>; output byte to port
>; repeat
>;
>LOOP1:
>  add  r28,r24   ; 1
>  adc  r29,r25   ; 1
>  adc  r30,r26   ; 1
>  lpm      ; 3
>  out  PORTB,r0  ; 1
>  rjmp LOOP1   ; 2 => 9 cycles
>
>I'm using the same AD557 8-bit DAC and the same look-up tables. I'm
>obviously doing something silly, but I can't see what it is. Can anyone
>help?
>
>Leon
>--
>Leon Heller, G1HSM
>Email: aqzf13@...
>http://www.geocities.com/leon_heller
>
>
>To unsubscribe from this group, send an email to:
>lpc2100-unsubscribe@yahoogroups.com
>
>
>
>Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>

Re: [lpc2100] Problem with DDS

2003-12-03 by Ben Dooks

... what is the compiler outputing for this code? do you have a disassembly of the code being produced? [snip] -- Ben Q:      What s a light-year? A:

Re: Problem with DDS

2003-12-03 by leon_heller

--- In lpc2100@yahoogroups.com, Ben Dooks <ben@f...> wrote:
> On Wed, Dec 03, 2003 at 10:44:28AM -0000, Leon Heller wrote:
> > I'm using the following code for software direct digital waveform
synthesis:
> > 
> > int main(void)
> > {
> >   unsigned int i;
> >   unsigned long int acc, adder;
> >   unsigned int ptr, temp;
> > 
> >   initPLL();
> >   MAMCR = 0;
> >   MAMTIM = 5;
> >   MAMCR = 2;
> >   VPBDIV = 0x01;
> >   portInit();
> >   //main loop
> >   //add value to accumulator
> >   //load byte from current table
> >   //output byte to port
> >   //repeat
> > 
> >   adder = 2000;               //set up adder
> >   acc = 0;                    //clear accumulator
> >   while (1)
> >   {
> >     acc = acc + adder;      //update phase accumulator
> >     ptr = (acc &= 0xFF);    //pointer into table
> >     IOSET = square[ptr] << 8;//output byte to port
> >     IOCLR = ~(square[ptr] << 8);
> >   }
> >   return 0;
> > }
> > 
> > but I can't get an equal mark-space ratio out of it for a square
wave, and
> > sine waves are completely screwed up.
> 
> what is the compiler outputing for this code? do you have a disassembly
> of the code being produced?
>

Thanks for the suggestion.

This is what I'm getting:

    while (1)
40000150 E3A0024E mov r0, #0xe0000004
40000154 E280090A add r0, r0, #0x28000
40000158 E59F1028 ldr r1, [pc, #40]
4000015C E3A022CE mov r2, #0xe000000c
40000160 E282290A add r2, r2, #0x28000
    {
      acc = acc + adder;      //update phase accumulator
40000164 E084400C add r4, r4, r12
      ptr = (acc &= 0xFF);    //pointer into table
40000168 E20440FF and r4, r4, #0xff
      IOSET = square[ptr] << 8;//output byte to port
4000016C E7D43001 ldrb r3, [r4, r1]
40000170 E1A03403 mov r3, r3, lsl #0x8
40000174 E5803000 str r3, [r0, #0]
      IOCLR = ~(square[ptr] << 8);
40000178 E7D43001 ldrb r3, [r4, r1]
4000017C E1E03403 mvn r3, r3, lsl #0x8
40000180 E5823000 str r3, [r2, #0]
40000184 EAFFFFF6 b -10 ; 0x40000164
40000188 4000062C andmi r0, r0, r12, lsr #0xc
    }

I'm not all that familiar with ARM assembler, but it looks about
right.  I'm using the Rowley tools, which use the GNU compiler.

Leon

Re: [lpc2100] Re: Problem with DDS

2003-12-03 by microbit

Hi Leon,

To check the value written you need this :

>       ptr = (acc &= 0xFF);    //pointer into table
> 40000168 E20440FF and r4, r4, #0xff

ptr is R4.

>       IOSET = square[ptr] << 8;//output byte to port
> 4000016C E7D43001 ldrb r3, [r4, r1]
> 40000170 E1A03403 mov r3, r3, lsl #0x8
> 40000174 E5803000 str r3, [r0, #0]

The ldrb instruction loads R3 with what R4, offset by R1, points to.
So you need to know what's in R1 to work out the offset, and thus what's
actually
written to IOCLR and IOSET

> I'm not all that familiar with ARM assembler, but it looks about
> right.  I'm using the Rowley tools, which use the GNU compiler.
>
> Leon

Best regards
-- Kris

Re: [lpc2100] Re: Problem with DDS

2003-12-03 by microbit

Also BTW, I think you need to mask off the other bits on I/O
(D0-D7, D16-D31), especially with the write to IOCLR.

I've actually been thinking of a boolean macro that turns IOSET,IOCLR into 
"one port", where you just write a zero or a one to the macro to set/clear
IO pins, and it does the 1 bit writing to CLR or SET for you.

-- Kris



----- Original Message ----- 
Show quoted textHide quoted text
From: "microbit" <microbit@...>
To: <lpc2100@yahoogroups.com>
Sent: Wednesday, December 03, 2003 11:54 PM
Subject: Re: [lpc2100] Re: Problem with DDS


> Hi Leon,
> 
> To check the value written you need this :
> 
> >       ptr = (acc &= 0xFF);    //pointer into table
> > 40000168 E20440FF and r4, r4, #0xff
> 
> ptr is R4.
> 
> >       IOSET = square[ptr] << 8;//output byte to port
> > 4000016C E7D43001 ldrb r3, [r4, r1]
> > 40000170 E1A03403 mov r3, r3, lsl #0x8
> > 40000174 E5803000 str r3, [r0, #0]
> 
> The ldrb instruction loads R3 with what R4, offset by R1, points to.
> So you need to know what's in R1 to work out the offset, and thus what's
> actually
> written to IOCLR and IOSET
> 
> > I'm not all that familiar with ARM assembler, but it looks about
> > right.  I'm using the Rowley tools, which use the GNU compiler.
> >
> > Leon
> 
> Best regards
> -- Kris
> 
> 
>       Yahoo! Groups Sponsor 
>      
>      
> 
> To unsubscribe from this group, send an email to:
> lpc2100-unsubscribe@yahoogroups.com
> 
> 
> 
> Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service. 
>

Re: [lpc2100] Problem with DDS

2003-12-03 by Robert Adsett

At 11:23 AM 12/3/03 +0000, you wrote:
>On Wed, Dec 03, 2003 at 10:44:28AM -0000, Leon Heller wrote:
> > I'm using the following code for software direct digital waveform 
> synthesis:
> >
> > int main(void)
> > {
> >   unsigned int i;
> >   unsigned long int acc, adder;
> >   unsigned int ptr, temp;
> >
> >   initPLL();
> >   MAMCR = 0;
> >   MAMTIM = 5;
> >   MAMCR = 2;
> >   VPBDIV = 0x01;
> >   portInit();
> >   //main loop
> >   //add value to accumulator
> >   //load byte from current table
> >   //output byte to port
> >   //repeat
> >
> >   adder = 2000;               //set up adder
> >   acc = 0;                    //clear accumulator
> >   while (1)
> >   {
> >     acc = acc + adder;      //update phase accumulator
> >     ptr = (acc &= 0xFF);    //pointer into table
> >     IOSET = square[ptr] << 8;//output byte to port
> >     IOCLR = ~(square[ptr] << 8);
> >   }
> >   return 0;
> > }
> >
> > but I can't get an equal mark-space ratio out of it for a square wave, and
> > sine waves are completely screwed up.

Strangely enough your original message doesn't seem to have propagated Leon.

There are definitely issues with how fast you can update the output ports 
though.  Given there is no delay in your loop that is likely to be having 
an effect.  If you insert a delay I expect that will square things up (of 
course you'll get a slower wave :()

Robert

" 'Freedom' has no meaning of itself.  There are always restrictions,
be they legal, genetic, or physical.  If you don't believe me, try to
chew a radio signal. "

                         Kelvin Throop, III

Re: [lpc2100] Problem with DDS

2003-12-03 by Robert Adsett

At 10:44 AM 12/3/03 +0000, you wrote:
>I'm using the following code for software direct digital waveform synthesis:

Ah, it just showed up.

>   adder = 2000;               //set up adder
>   acc = 0;                    //clear accumulator
>   while (1)
>   {
>     acc = acc + adder;      //update phase accumulator
>     ptr = (acc &= 0xFF);    //pointer into table
>     IOSET = square[ptr] << 8;//output byte to port
>     IOCLR = ~(square[ptr] << 8);
>   }
>   return 0;
>}
>
>but I can't get an equal mark-space ratio out of it for a square wave, and
>sine waves are completely screwed up.
>
>The following code for an AVR works very well:
>
>; main loop
>;
>; r28,r29,r30 is the phase accumulator
>;   r24,r25,r26 is the adder value determining frequency
>;
>;  add value to accumulator
>; load byte from current table in ROM
>; output byte to port
>; repeat
>;
>LOOP1:
>   add  r28,r24   ; 1
>   adc  r29,r25   ; 1
>   adc  r30,r26   ; 1
>   lpm      ; 3
>   out  PORTB,r0  ; 1
>   rjmp LOOP1   ; 2 => 9 cycles
>
>I'm using the same AD557 8-bit DAC and the same look-up tables. I'm
>obviously doing something silly, but I can't see what it is. Can anyone
>help?

OK, this makes things a little more clear.

Q: Is your distortion coming from loop to loop delay or from the delay 
between set and clear?  (I suspect the latter).

Robert

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.