Skip to main content
Topic: Patch to add hardware PWM support down to 2Hz (Read 5889 times) previous topic - next topic

Patch to add hardware PWM support down to 2Hz

Hi, while writing a binary mode library for the Bus Pirate I noticed that it's possible to set the hardware PWM down to 2 Hz, but the interactive ASCII interface (command [tt:]g[/tt:]) only provides options down to 1 KHz. I made a small patch to the firmware, which adds a new command [tt:]G[/tt:] that asks for the PWM frequency in Hz. Using an external frequency counter I found this working down to 2 Hz on my BPv3.5, although I'm not sure if it's a limitation of my frequency counter or of the chip that 1 Hz doesn't work (so 1 Hz value is allowed).

Some observations:

1) I needed to enable [tt:]getlong[/tt:] for BPv3, previously it was only used with BPv4.

2) Confusingly [tt:]getlong[/tt:] is actually the equivalent of [tt:]getnumber[/tt:] and not [tt:]getint[/tt:] as one might think, and there is no [tt:]long[/tt:] version of [tt:]getint[/tt:]. As such it is not possible to specify a command-line argument to "G" with a frequency higher than [tt:]INT_MAX[/tt:]. I don't see this as a major problem, though, since one can use the "g" version in KHz with higher frequencies (that wouldn't have 1 Hz precision anyhow).

3) I also changed the [tt:]g[/tt:] command (PWM in KHz) to use my modified method for calculating the register values. This saves code space so the size impact of adding this command is fairly minimal (essentially just [tt:]getlong[/tt:]). However, this means that any bugs in my patch will also affect the old "g" command. I did test this with various options, though, and my calculation method is simpler with fewer magic numbers.

(There is still an internally used [tt:]updatePWM[/tt:] that I didn't touch. Personally I think the cleanest solution would be to have that use the same PWM calculation methods as well instead of duplicating everything for the interactive and non-interactive versions as seems to be done throughout the codebase.)

4) I don't know where the thresholds used for prescaler selection come from, but I kept the existing values (4 KHz, 31 KHz, and 245 KHz).

The patch is against the latest SVN sources, and can be applied in the firmware sources directory ([tt:]trunk/Firmware[/tt:]) with [tt:]patch -p0 <my_patch.diff[/tt:].


Oh, the patch itself:
http://arkku.com/misc/buspirate_hz_pwm_patch.diff

Re: Patch to add hardware PWM support down to 2Hz

Reply #1
Patched firmware in use:

Code: [Select]
2WIRE>g
1KHz-4,000KHz PWM
Frequency in KHz
(50)>10
Duty cycle in %
(50)>
PWM active
2WIRE>g
PWM disabled
2WIRE>G
PWM 2-4000000Hz
Frequency in Hz
(500)>10
Duty cycle in %
(50)>
PWM active
2WIRE>G
PWM disabled

Frequencies confirmed by measuring the AUX output.

Re: Patch to add hardware PWM support down to 2Hz

Reply #2
I would like to have this at least in BP V4 firmware.

Re: Patch to add hardware PWM support down to 2Hz

Reply #3
Thank you for the patch. Do you think we could combine it into a single command by adding a 'f' submenu that prompts for Hz range or KHz range?

Adding this much code in the BPv3 firmware could be problematic because we are running out of room, but this should go in v4 for sure.

I zipped and attached the patch here for reference too.
Got a question? Please ask in the forum for the fastest answers.

Re: Patch to add hardware PWM support down to 2Hz

Reply #4
[quote author="ian"]Thank you for the patch. Do you think we could combine it into a single command by adding a 'f' submenu that prompts for Hz range or KHz range?[/quote]

How would that "f" command work, do you mean that it would have three questions (Hz/KHz, frequency, duty cycle)? If yes, then it would be better, in my opinion, to just always ask the frequency in Hz; it's easier to just type "000" after the KHz than read and answer another prompt. Or if you mean that it should toggle the behaviour of the "g" command between Hz and KHz, then that has the problem of introducing a hidden state into the system + if there is an additional menu for this functionality why not just the simpler (and smaller code) of the current "g"/"G"…

Personally I think there are only two reasons to have the KHz version at all:

1) Compatibility with existing scripts that may rely on "g" to take KHz arguments.
2) There is no [tt:]long[/tt:] equivalent of [tt:]getint[/tt:] so "G" cannot take command-line frequencies over 32,767Hz (but can in the interactive menu due to [tt:]getlong[/tt:]).

[quote author="ian"]
Adding this much code in the BPv3 firmware could be problematic because we are running out of room, but this should go in v4 for sure.
[/quote]

Yes, the original patch adds 1161 bytes of code to BPv3 when compiled in MPLAB 8 (no optimizations). I tried to tweak it for smaller code size and got it down to 867 bytes (and also changed [tt:]updatePWM[/tt:] to use the same PWM setup routine instead of duplicating all the code). With MPLAB X none of this is particularly relevant, since with [tt:]-Os[/tt:] (size optimization) enabled the build is over 14K smaller. (I would argue for transitioning to MPLAB X [tt:]-Os[/tt:] builds regardless of this patch, but that is another topic. =)


In any case, the new patch (smaller compiled code) is attached (and also uploaded to the URL in the first post). (This patch is to be applied instead of, not on top of, the original patch I posted above. Use [tt:]svn revert AUXpin.* procMenu.*[/tt:] to undo the first patch if already applied.)

Re: Patch to add hardware PWM support down to 2Hz

Reply #5
Thank you so much. Maybe entering hz is better.

Quote
I would argue for transitioning to MPLAB X -Os builds regardless of this patch, but that is another topic. =)

I have no immediate problems with that, but in the past optimizations have had some unexpected effects.
Got a question? Please ask in the forum for the fastest answers.

Re: Patch to add hardware PWM support down to 2Hz

Reply #6
Note: there was a problem in the previous patch when using BASIC scripting to do frequencies over 32KHz: the last line of [tt:]updatePWM[/tt:] in [tt:]AUXpin.c[/tt:],

[tt:]PWMstart(PWMfreq * 1000, PWMduty);[/tt:]

needs to be

[tt:]PWMstart((long)PWMfreq * 1000, PWMduty);[/tt:]

or the value will overflow. I've updated the patch posted above, but the two downloaders of the previous version should change this line.

On another note, BASIC scripting command [tt:]freq[/tt:] seem actually quite silly now that it takes KHz only. I did not add a Hz equivalent, though, since again there is the problem of [tt:]int[/tt:] having insufficient range to represent the full PWM range in Hz,  and there's no [tt:]long[/tt:] equivalent of [tt:]getint[/tt:] (which would be trivial to make but would increase code size again).

I'm also not sure how you would prefer to deal with the KHz vs Hz in BASIC? As BASIC hasn't been available on <v4 by default(?), I don't think it would be particularly problematic to break compatibility with existing BASIC scripts and just use Hz, and also on the v4 the size issue of creating a [tt:]long[/tt:] version should not be, well, an issue. (But, for what it's worth, I only have v3.5 myself and the BASIC scripting still fits, even with this patch.)

Re: Patch to add hardware PWM support down to 2Hz

Reply #7
Just for BASiC reference. The parallax basic "Freqout", uses a stepping unit, of only 15bits, and is 1 to 1Hz for bs2/bs2e, but differs for the other models, 1 to 6.03Hz on the higher end.

Re: Patch to add hardware PWM support down to 2Hz

Reply #8
Hello, how do I apply the patch?  (I've never done it before)