Using the PWM Capability of the 908JL16 to Generate CTCSS Tones

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

Using the PWM Capability of the 908JL16 to Generate CTCSS Tones

Jump to solution
4,948 Views
joeburch
Contributor III

Hello folks,

 

I was wondering if someone would be good enough to give me some general help on the following topic:

 

Using a 908JL16, 28 pin device, I'm attempting to use it to both generate and (later) decode the sub audible tone frequencies that range from 67 Hz to 250.3 Hz.  If I can get the generation capability working, I believe that I can make the decoding portion work on my own.

 

I've read some of the posts here on using PWM to generate the tones in other processors.  Using an XCEL spead sheet, I computed (and plotted) an accurate sine wave in a 256 byte table.

 

The tones (of a predetermined frequency) will be generated continuously when the M/P is in the transmit mode, and I would like to use Timer 1 for this purpose, and will be using a 9.8304 Mhz external oscillator.

 

Some questions:

 

1) Must I use the buffered mode when stepping through the SineTable?

 

2) How should the timers be set up / serviced?

 

3) What interruots are required?

 

4) How do I compute the 'time slices' as a function of the desired frequency (e.g. 100.0 Hz, 250.3, etc)?

 

Any code specific examples will be most appreciated.

 

I did try reading through AN-1777, but unfortunately got lost when trying to figure out the HC-08 code for dual chord tone synthesis.

 

Thanks, in advance, for any help.

 

Joe Burch

Labels (1)
0 Kudos
Reply
1 Solution
3,615 Views
bigmac
Specialist III

Hello Joe,

 

I don't think what you are proposing is feasible, certainly not with the 908JL16 and a 2.5MHz bus frequency.

 

On the basis that you will need to resolve the frequency to 0.1Hz, the period resolution of a full cycle would need to be 1.6us at a frequency of 250Hz, the worst case scenario.  At 67Hz the period resolution would increase to 22us.

 

Now the per step period resolution will depend on the number of steps per cycle.  For the moment let's assume 64 steps.  This would mean that the period resolution per step would become 25ns for a frequency of 250Hz, or a PWM clock of at least 40MHz.  This is more than an order of magnitude higher than the 908JL16 can provide.

 

With 256 steps per cycle, the PWM clock would need to be 160MHz.  This is obviously not the best method for generating a sine wave that requires good frequency resolution.

 

One method that can provide good frequency resolution, with more moderate clock rate, is the Direct Digital Synthesis (DDS) method.  This would normally require a proper D/A converter for the tone output.  I suggest that you Google this subject to find out more.  In the more distant past, I actually used a special chip that provided audio tones by this method.

 

Regards,

Mac

 

View solution in original post

0 Kudos
Reply
29 Replies
966 Views
joeburch
Contributor III

Hi Mac,

 

Thanks for your time.

 

No, I kept the initialization code up front, shortly after the M/P powers up:

 

     mov   #$30,t1sc           ; temporarily stop the timer and clear the prescale bits
     ldhx    #0080                ; initial PWM duty 50%
     sthx    t1ch0h
     bclr    5,t1sc                 ; re-enable timer

 

I also had included it in the pwminit routine.  I checked it on the CodeWarrior simulator.

 

Her'es the code to initialize the pwm mode:

 

initpwm
                  
     ldx ctcss                  ; get ctcss value
     lslx                            ; adjust word address
     clrh
     lda ctcss_tbl,x         ; read high byte
     sta freq                    ; store it
     lda ctcss_tbl+1,x       ; read low byte
     sta freq+1                 ; store it
     mov #$08,ddsreg
     clr ddsreg+1
     clr ddsreg+2
     clr track                     ; clear table entry
    
     bset 5,t1sc                ; stop timer   
     mov #$5A,t1sc0          ; unbuffered PWM, clear on compare
     bclr  5,t1sc                ; re-enable timer
     cli
     rts

 

and the code for the interrupt (along with your test code):

 

_toc0int

    bclr 7,t1sc0
    bil toc01
    clr t1ch0l
    rti

toc01                       
    pshh
                              ; Add FREQ value to DDSREG
    lda    ddsreg+2           ;
    add    freq+1             ;
    sta    ddsreg+2           ;
    lda    ddsreg+1           ;
    adc    freq               ;
    sta    ddsreg+1           ;         
    and    #$F0               ; Mask upper nybble         
    nsa                       ;         
    psha                      ;
    lda    ddsreg             ;
    adc    #0                 ;
    sta    ddsreg             ;
    and    #$0F               ; Mask lower nybble         
    nsa                       ;         
    ora    1,SP               ; Combine nybbles         
    ais    #1                 ; Adjust stack pointer
    tax                     ;
    clrh                      ;
    lda    sin_tbl,x          ; Fetch value from sine table
    clr    t1ch0h
    sta    t1ch0l             ; Update TIM channel duty
                                                           
    BRSET  3,ddsreg,TOC02     ; Branch if phase output MSB is set
    BCLR   6,prtb                          ; Clear test pin output
    BRA    *+4                                ; Skip next always
   
TOC02:

    BSET   6,prtb             ; Set test pin output
   
    inc    track              ; set up for next interrupt.
    pulh                       
    rti                       ; return

 

The reason for the non varying pulse was that the TAX instruction was somehow omitted (by me).  Now the pulse varies (ramps up and ramps down), but the program is running way too slow.

 

It looks like I'm not going to be able to join the ranks of successful PWM'ers on the JL-16.

 

Any last thoughts??

 

Joe

0 Kudos
Reply
966 Views
bigmac
Specialist III

Hello Joe,

 

I still do not see where you have set the value of T1MOD register.

 

Regards,

Mac

 

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

I hate to bug you again on the topic of ctcss tones, but I hope that you can point me in the right direction.

 

The complementary software to generating the ctcss tones is to uncode them.  I have been trying to use the input capture feature of the JL16's timer to no avail.

 

Specifically, I set the modulo counter up to generate a 170 ms 'time base' and then took 5 cumulative 'samples' of the input pulse frequency (input capture) which I then ran through a table.................

 

Would you be so good as to go about this task.

 

Thanks, in advance, for your assistance.

 

Joe Burch

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

Just one more thought / question.

 

Would counting the timer overflows between input captures work?

 

I could build up a table to account for plus or minus (.5Hz) to hunt after I have the number of overflows.

 

Joe

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

With regard to the MOD setting, I had placed it up front in the initialization routine, but had somehow assigned the wrong value to it in the variables portion of the program.

 

So, I stuffed 00FF into the mod and tried it again with a simple 2 stage filter (2 - 2.7K and 2 - .1 mf caps on the output).

 

Man, that's a sine wave that you'd be proud to take to dinner!  Only a slight case of jitter and a nice, consistent waveform.

 

Even with the R/C oscillator, the frequency is very close - e.g. 250.2 (for 250.3) and 100.0 (for 100.0)

 

However, on all the frequencies below 100.0 (e.g. 67.0. 97.4), the sinewave output is somewhat less in amplitude. and the counter shows them all at 600 hz.  What could be causing this?

 

Thanks again,

 

Joe

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

I spoke prematurely.  I'll run all of the tones later today to see what variances (if any).

 

Joe

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

You are truly a wizard! 

 

The 'problem' with some of the tones reading 600 Hz. was because of a 'hole' in the data table.  Looks like your code can generate - with precision - up to 600 Hz in .1 Hz increments.

 

My next project is to write the code using input capture to determine the received tone.  With all the help you've given me, I should be able to do this myself.

 

Even with the external R/C combination, the internal oscillator arrangement is very accurate, which leads me to my next question. 

 

If I were to use an external trimmer resistor to calibrate the clock so that the ctcss tones were 'right on (I think their 'tolerance' is something line + or - .5 Hz), do you think that this would be a reasonable compromise to an external oscillator??  I ask this question because I would lose a pin with the external crystal oscillator and this particular application is port limited.

 

Will the M/P's ambient temperature cause the internal oscillator to 'drift', do you think??

 

Whenever I get the tone receiving code working, would it be worthwhile to post everything (code + tables) here on this site so that others can benefit from your work??

 

Joe

0 Kudos
Reply
966 Views
rocco
Senior Contributor II

Hi Joe,

 

Yes, Mac is a wizard.

 

I would not trust an R/C oscillator to not drift over voltage and temperature. But, rather than using a crystal, you can use a canned cmos oscillator and save that pin. It would also less parts to add, although a few dollars more. It is all I ever use, for reliability reasons.

 

And, yes, please post the code. I would love to see it.

0 Kudos
Reply
966 Views
joeburch
Contributor III

Hi Mac,

 

At least some progress today.

 

I coded all the CTCSS values in a 16 bit format per the formula you provided.  It was a bit of a tussle, but I finally got the M/P generating interrupts and can see a series of pulses on the Channel 0 output.

 

What I see on the scope is a continuous pulse that smoothly increases in duration from near 0 to about 82 us in just under 2 seconds.  It starts near 0, ramps up to 82us, and then goes back to zero in about the same time frame.  It is the same pulse no matter what CTCSS tone is selected.

 

I think everything is coded OK but will go back tonite or tomorrow when I'm fresher.

 

I have not yet activated the external clock and am running on the R/C oscillator.

 

Any thoughts or suggestions??

 

Thanks again,

 

Joe Burch

0 Kudos
Reply