A while back I was working on a project to modulate a radio signal using a Panda and it seemed like people thought it couldn’t be done without using RLP… So I used RLP. However I recently realized the OutputCompare class could be use to create essentially the same thing with specific timings for the upper and lower frequencies. And it works!
One thing I’ve noticed is that the non-RLP code seems to focus more of the energy in the correct frequencies (2125 and 1775 Hz in this case) while the signal itself isn’t quite as clean, which is ok. Here is the non RLP received spectrum and I’ll post the RLP one next.
The RLP one is using PWM and is turning it on and off while the non RLP one is not using PWM. Any idea what would cause the differences? I would expect the PWM generated signal to be both cleaner (which it is) and more focused near the frequencies (which it isn’t).
somewhere there is a thread about Stopping PWM Clean. if i recall correctly then there is a register you must set else changing the pwm has immediate effect, chopping the current cycle short, which will give you nasty spread and such…
Ok, I’m already doing the PWM in RLP with registers so probably if I look over the register based code and do it that way I’ll get the best of both worlds. Thanks!
I looked at the registers being used and couldn’t see where that was occurring in your code. Here is what I currently have, what changes do you suggest?
#define TCR_CNT_EN 0x00000001
#define TCR_RESET 0x00000002
#define TCR_PWM_EN 0x00000008
#define PWMMR0R 1 << 1
#define LER0_EN 1 << 0
#define LER1_EN 1 << 1
#define LER2_EN 1 << 2
#define LER5_EN 1 << 5
#define PWMENA1 1 << 9
#define PWMENA2 1 << 10
#define PWMENA5 1 << 13
#define PINSEL_BASE_ADDR 0xE002C000
#define PINSEL3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x0C))
#define PWM1_BASE_ADDR 0xE0018000
#define PWM1TCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x04))
#define PWM1PR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x0C))
#define PWM1MCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x14))
#define PWM1MR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x18))
#define PWM1MR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x1C))
#define PWM1MR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x20))
#define PWM1MR5 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x44))
#define PWM1PCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x4C))
#define PWM1LER (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x50))
#define UART0_BASE_ADDR 0xE000C000
#define U0THR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00))
#define MICROSECOND 18
int PwmStart(unsigned int frequencyHz, unsigned char duty)
{
PINSEL3 |= 0x20220; /* set GPIOs for all PWM1, PWM2 & PWM5 */
PWM1TCR = TCR_RESET; /* Counter Reset */
PWM1PR = 0x00; /* count frequency:Fpclk */
PWM1MCR = PWMMR0R; /* reset on PWMMR0, reset TC if PWM0 matches */
//avoid increase in compile size by avoiding float math and scaling numebrs up
long CYCLE_WIDTH = (1000000000 / frequencyHz) * MICROSECOND / 1000;
PWM1MR0 = CYCLE_WIDTH; /* set PWM cycle */
//avoid increase in compile size by avoiding float math and scaling numebrs up
long rate = CYCLE_WIDTH * ((duty * 1000) / 100) / 1000;
PWM1MR1 = rate;
PWM1MR2 = rate;
PWM1MR5 = rate;
/* PWM latches enabled, ready to start */
PWM1LER = LER0_EN | LER1_EN | LER2_EN | LER5_EN;
/* All single edge, all enable */
PWM1PCR = PWMENA1 | PWMENA2 | PWMENA5;
PWM1TCR = TCR_CNT_EN | TCR_PWM_EN; /* counter enable, PWM enable */
return 1;
}
Yeah, once I ponder the original 2 images in this thread a bit more I think the “focus” is the same but because the frequencies aren’t exactly right the dots are spread out a bit more instead of the nice fine lines which are more visible in the PWM case. So I’m guessing that is probably as good as it gets without introducing hardware frequency filtering.
Are these generated by spectrum analyzer? You know that PWM generates squared signal (not sinusoidal signals) so you will never see pure power at any frequency.