Lookup table to Generate PWM tone

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Lookup table to Generate PWM tone

6,032 Views
mylim
Contributor IV
Hi guys, do you have any example on Lookup Table for PWM tone generation?
 
Thanks.
MY
Labels (1)
0 Kudos
29 Replies

1,596 Views
tonyp
Senior Contributor II
Check this thread on a similar topic.
0 Kudos

1,596 Views
mylim
Contributor IV
Hi Tony,
Basing on the code from the thread;

Code:
lb00                ldhx      #TabSinlb01                clr       TPMC1VH                    mov       x+,TPMC1VL                    mov       #$28,TPMSC                    brclr     TOF,TPMSC,*                    cphx      #EndTabSin                    blo       lb01                    bra       lb00TabSin              dc.b      $A0,$A0,$da,$da,$A0,$A0,$da,$da                    dc.b      $A0,$A0,$da,$da,$A0,$A0,$da,$daEndTabSin

Where/how does the pointer increment in order to load the next TabSin value to x?
Thanks.
 
Regards,
MY
0 Kudos

1,596 Views
Ake
Contributor II
Hi,
The pointer gets incremented at
                   mov       x+,TPMC1VL
 
and when it hits EndTabSin, it gets reset to TabSin.
 
Note that the program assumes that the conversion table starts at address $xx00.
So put an
  org $xx00
before the TabSin label.
 
 
Regards,
Ake
0 Kudos

1,596 Views
tonyp
Senior Contributor II


Ake wrote:
Note that the program assumes that the conversion table starts at address $xx00.
So put an
  org $xx00
before the TabSin label.


No such assumption!
0 Kudos

1,596 Views
tonyp
Senior Contributor II
mov x+,TPMC1VL
(the + is for auto-increment after the move)

The TabSin table value isn't loaded to X, it's copied ('moved') from memory to memory using HX as pointer


Message Edited by tonyp on 2007-11-22 10:30 AM
0 Kudos

1,596 Views
mylim
Contributor IV
Hi Tony,
does that mean once this routine is called, I do not require to have any external pre-calculated pointer for #TabSin?
It will increment itself in the routine until it matched #EndTabSin?
 
To generate tone, it's preferable to init my pin to PWM or Output Compare?
Any difference between these 2 as PWM will also either set/clr output on compare?
 
Does the channel compare value = TPMxCxV?
Thanks
 
Regards,MY
0 Kudos

1,596 Views
tonyp
Senior Contributor II

mingyee wrote:
does that mean once this routine is called, I do not require to have any external pre-calculated pointer for #TabSin?

Read the code carefully.  First instruction initializes HX to the beginning of the table.

To generate tone, it's preferable to init my pin to PWM or Output Compare?
Any difference between these 2 as PWM will also either set/clr output on compare?

PWM uses an Output Compare.  Normally, varying the pulse-width changes the volume, while varying the frequency changes the tone.  (How you do it depends on your actual hardware design.)
0 Kudos

1,596 Views
mylim
Contributor IV


tonyp wrote:
PWM uses an Output Compare.  Normally, varying the pulse-width changes the volume, while varying the frequency changes the tone.  (How you do it depends on your actual hardware design.)

Hi Tony,
As I'm aware, the frequency can be manipulated thru TPMC1VL.
But how do I come about the Pulse Width?
I'm a little confused here.
Thanks.
 
Regards,
MY

 
0 Kudos

1,596 Views
tonyp
Senior Contributor II
You'll have to read the various references for detailed explanations.  In short, (quoting from one such reference):

The period of this PWM signal is determined by the setting in the modulus register
(TPMMODH:TPMMODL). The duty cycle is determined by the setting in the timer channel value register
(TPMCnVH:TPMCnVL). The polarity of this PWM signal is determined by the setting in the ELSnA
control bit.
0 Kudos

1,596 Views
mylim
Contributor IV
Hi Tony,
I've tried the code with my TPM modulo ctr $FF00.
I've obtained the graph below basing on circuit attached.
I'm not able to get a 'nice' sine wave is it due to my hardware filtering problem?
Please advise.
Thanks.
 
Regards,
MY
0 Kudos

1,596 Views
bigmac
Specialist III
Hello MY,
 
It would appear the primary reason your code doesn't generate a sine wave is that the table data you are using does not represent a sequence of amplitude values within a sine wave.
 
Firstly, you will need to decide how many PWM output periods should represent one sine wave cycle.  More periods per cycle should give simpler filtering, but there will be a trade off between amplitude resolution and sine wave frequency.
 
For example, let's assume you require 1000Hz sine wave using 10MHz TPM clock rate, i.e. 10,000 bus cycles per output cycle.  One possible solution would be to have 100 PWM periods, with each PWM period consisting of 100 TPM clock cycles ( 1% amplitude resolution). and this would seem a reasonable compromise.  Using these figures, the size of the lookup table would need to be 100 bytes.
 
Since the PWM generates an output amplitude between 0 percent and 100 percent, the sine waveform will be offset so that the negative minimum corresponds with 0 percent, and the positive maximum with 100 percent amplitude.  The lookup table might have the following structure -
 
Table index:  Entry value:
    0             50
   25            100
   50             50
   75              0
 
The intermediate values, in increments of 3.6 degrees, would need to be calculated and scaled to follow the sine waveform.
 
Since the PWM frequency for the above example would be 100 kHz,  the cut-off frequency for the output filter would be non-critical, perhaps a value of 2 - 3 kHz.  A two-pole filter will probably be adequate, however, I would probably use an active filter type for better control of the filter characteristic, and to provide output buffering.
 
Regards,
Mac
 
0 Kudos

1,596 Views
PeterHouse
Contributor I
You could have the lookup table only contain the data for a single quadrant of the sine since all four quadrants will have identical values and will differ only in output order and magnitude.  If you have amplitude resolution of 8 bits your table would contain only seven bits and half the time would be subtracted from 128 and the other half added to 128.  This could reduce your table size to 25% or you could inccrease the frequency resolution - your call.

I am sure Mac knows this and left it off for simplicity!

Good Luck,

Peter House
0 Kudos

1,596 Views
mylim
Contributor IV
Hi, I've tried to implement a table like below which i think it looks more like a sine table according to your comment.
 
Code:
tone        ldhx   #tonetab 
tone1       clr    TPM2C0VH
            mov    X+,TPM2C0VL
            mov    #$28,TPM2SC
            brclr  TPM2SC_TOF,TPM2SC,*
            cphx   #tonetabend
            blo    tone1
            rts
           
tonetab     fcb    $00,$7F,$94,$A7,$B9,$C8,$D5,$DE,$E4,$E6
            fcb    $E4,$DE,$D5,$C8,$B9,$A7,$94,$7F,$6C,$59
            fcb    $47,$38,$2B,$22,$1C,$22,$2B,$28,$47,$59,$6C
tonetabend   
 
I'm having another problem which after executing
                 mov    X+,TPM2C0VL
I do not see the X value written into TPM2C0VL register.
 
Please advise.
Thanks.
 
regards,
MY
Message Edited by t.dowe on 2009-10-27 01:19 PM
0 Kudos

1,596 Views
bigmac
Specialist III
Hello MY,
 
There are still some problems with your lookup table.  Since you requre symmetry between the positive and negative half-cycles of the waveform, the table should have an even number of entries, possibly 32 (not 31), and the first entry should not be zero.  There also seems to be some degree of asymmetry between positive and negative peak amplitudes.
 
For a 32 byte table, the following would seem to be a little more accurate for a sine shape -
 
tonetab:
  fcb  128,148,166,184,199,211,220,226
  fcb  228,226,220,211,199,184,166,148
  fcb  128,108,90, 72, 57, 45, 36, 30
  fcb  28, 30, 36, 45, 57, 72, 90,108
 
For the range of values you have selected, the TMOD value for the TPM module should be 228 ($00E4) minimum.  Higher values will affect both output amplitude and sine frequency.  The sine wave period will be 32 times the TPM overflow period. 
 
For a TPM clock of 2.0 MHz, and a TMOD value of, say 255, the sine frequency should be about 244 Hz, and the PWM frequency 7.8 kHz.  The low-pass filter cut-off frequency should be about 500 Hz, perhaps somewhat higher if a CR passive filter is used.
 
Regards,
Mac
 
0 Kudos

1,596 Views
mylim
Contributor IV
Hi Bigmac,
I've tried using the sine table you gave me & the TPM2MOD value.
The waveform doesnt seems quite right.
 
Another thing is that after executing mov    X+,TPM2C0VL
I still can't see the respective Tonetab value on the memory table in the debug window.
Doesnt this mean the value is not written into the register?
 
Thanks.
 
regards,
mingyee
 
Message Edited by t.dowe on 2009-10-27 01:21 PM
0 Kudos

1,596 Views
bigmac
Specialist III
Hello MY,


mingyee wrote:
Hi Bigmac,
I've tried using the sine table you gave me & the TPM2MOD value.
The waveform doesnt seems quite right.
 
Another thing is that after executing mov    X+,TPM2C0VL
I still can't see the respective Tonetab value on the memory table in the debug window.
Doesnt this mean the value is not written into the register?


I think there may be some confusion about the operation of the mov instruction.  The value within H:X represents the address of the current table element, not the contents of the table.  The value within the table is then moved into TPM2C0VL register.  You will need to view the register to see whether its value is altering in accordance with the table.

 

I can see some other problems and issues -

 

The code is intended for edge aligned PWM, not centre aligned as you appear to be operating.  The instruction "mov    #$28,TPM2SC" seems inappropriate for the AW60 device, as this enables centre aligned mode.  Using BUSCLK as the TPM clock source, and no overflow interrupt, the value $08 appears more suitable.

 

To what value do you initialise the TPM2C0SC register?  I suspect this should be a value of $28.

 

How many times does the "tone" sub-routine repeat to produce your plotted output (it appears to provide an output over about a 250 ms period)?  Each call of the sub-routine will output a single sine wave cycle.  For the anticipated output frequency, 250 ms would correspond to about 60 cycles.  However, you will really need to use continuous output so that the filtered waveform can settle properly.

 

Regards,

Mac

0 Kudos

1,596 Views
mylim
Contributor IV
 
The code goes;
Code:
        mov    #$28,TPMSC    ; TPM: No int, ext source, prescale 1
          clr    PNTR          ; Initialise pointer value
          clrh
LOOP1:    ldx    PNTR
          ldx    TabSin,x      ; Get byte value from table
          sthx   TPMC1V        ; Set PWM value
          inc    PNTR          ; Increment for next table entry
          brclr  TOF,TPMSC,*   ; Wait for timer overflow
          mov    #$28,TPMSC    ; Clear overflow flag
          bra    LOOP1         ; Loop always

 
I'm still unable to write my lookup table value into the TPM2C0VL.
Is there anything wrong?
I've attached the debug window & waveform captured below.
Btw, I'm using MC9S08AW60CFG.
Please advise. Thanks.
 
Regards,
MY
 
Message Edited by t.dowe on 2009-10-27 01:23 PM
0 Kudos

1,596 Views
bigmac
Specialist III
Hello MY,


mingyee wrote:
 
The code goes;
Code:
       mov    #$28,TPMSC    ; TPM: No int, ext source, prescale 1          clr    PNTR          ; Initialise pointer value          clrhLOOP1:    ldx    PNTR          ldx    TabSin,x      ; Get byte value from table          sthx   TPMC1V        ; Set PWM value          inc    PNTR          ; Increment for next table entry          brclr  TOF,TPMSC,*   ; Wait for timer overflow          mov    #$28,TPMSC    ; Clear overflow flag          bra    LOOP1         ; Loop always

 
I'm still unable to write my lookup table value into the TPM2C0VL.
Is there anything wrong?
I've attached the debug window & waveform captured below.
Btw, I'm using MC9S08AW60CFG.

You will note that the original thread required a 256 byte table size, and the above code assumes such a size.  This means that, with your 32 byte table, you are overflowing into "garbage" data, as reflected by your waveform plot.

The code will need to be modified to suit the smaller table size, possibly with the "inc  PNTR" instruction replaced by the following code -

     lda   PNTR
    inca
    and   #$1F
    sta   PNTR

This will restrict the value of PNTR to the range 0 - 31.

Regards,
Mac

 
Added p/n to subject.


Message Edited by NLFSJ on 2007-11-26 06:11 AM
0 Kudos

1,596 Views
mylim
Contributor IV
Hi all.. I'm back again with some quite similiar question.
I'm able to generate the sine wave tone perfectly.
However, I'd like to know how to generate a midi tone.
Do you guys have any example of doing it?
Thanks in advance.
 
Thanks
 
Regards
MY
0 Kudos

1,596 Views
mylim
Contributor IV


bigmac wrote:
The code will need to be modified to suit the smaller table size, possibly with the "inc  PNTR" instruction replaced by the following code -

     lda   PNTR
    inca
    and   #$1F
    sta   PNTR

This will restrict the value of PNTR to the range 0 - 31.

Regards,
Mac



HI Bigmac,
The above changes works for me.
Thanks.
However the mov    X+,TPM2C0VL portion still doesnt work.
At least I'm able to get it working though.
I've changed the TPM2SC to $08, TPM2C0SC is $28 & the TPM2MOD = $E4


bigmac wrote:

How many times does the "tone" sub-routine repeat to produce your plotted output (it appears to provide an output over about a 250 ms period)?  Each call of the sub-routine will output a single sine wave cycle.  For the anticipated output frequency, 250 ms would correspond to about 60 cycles.  However, you will really need to use continuous output so that the filtered waveform can settle properly.

Regards,
Mac



I only run the routine once cause I using it to generate a beep tone when a button is pressed.
Currently the Sincewave is running at approx 500Hz.
If i were to increase the sine wave frequency, I should decrease the TPM2MOD??
U mentioned that $E4 for TPM2MOD is the minimum, so how do I come about to increase the Since Wave Frequency in this case?
Do i need to increase my 32 steps?
What is the formula to calculate this?
 
Thanks.
 
Regards,
MY


Message Edited by mingyee on 2007-11-26 09:44 AM
0 Kudos