Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug #169 - analogWrite #195

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

micooke
Copy link
Contributor

@micooke micooke commented Sep 29, 2017

wiring_analog_* : fallback to digitalWrite if no available PWM channel (copied from AVR core)
wiring_analog_nRF52.c : convert pwmChannelPins & pwmChannelSequence -> pwmContext to semi-standardise pwm pin allocation and pwm status between nRF51 and nRF52
wiring_private.h : Move pwm structures defines out of wiring_analog_* into wiring_private and make the instantiation of these structure externs instead of statics
wiring_digital.c : disable the appropriate pwm timer when a digitalWrite is sent to an allocated (from analogWrite) pwm pin, and free up the pwm channel for re-allocation

wiring_analog_* : fallback to digitalWrite if no available PWM channel (copied from AVR core)
wiring_analog_nRF52.c : convert pwmChannelPins & pwmChannelSequence -> pwmContext to semi-standardise pwm pin allocation and pwm status between nRF51 and nRF52
wiring_private.h : Move pwm structures defines out of wiring_analog_* into wiring_private and make the instantiation of these structure externs instead of statics
wiring_digital.c : disable the appropriate pwm timer when a digitalWrite is sent to an allocated (from analogWrite) pwm pin, and free up the pwm channel for re-allocation
@micooke
Copy link
Contributor Author

micooke commented Sep 29, 2017

Tidy-up of #193

@micooke micooke changed the title Fix bug #169 Fix bug #169 - analogWrite Sep 29, 2017
Copy link
Owner

@sandeepmistry sandeepmistry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@micooke Thanks for submitting!

}
}

// fallback to digitalWrite if no available PWM channel
if (ulValue < 128)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the write resolution be higher than 8-bits? If so, we need to adjust this.

Copy link
Contributor Author

@micooke micooke Oct 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and on it!

One thing i noticed is that the read and write resolution isnt bounded and for the NRF52 they are stored as signed integers so you could set the read or write resolution to +/-2e9!

If its alright ill add a static int with the half max value and a switch statement to set it in writeResolution so that valid values are used (and so they arent re-calculated on each analogWrite)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference;

  • nRF51 TIMER1 (the only timer currently used for PWM) is either 8b or 16b write resolution
  • nRF52 is up to 32b write resolution for all 12 PWM channels

@@ -86,18 +93,42 @@ void digitalWrite( uint32_t ulPin, uint32_t ulVal )

ulPin = g_ADigitalPinMap[ulPin];

for (uint8_t i = 0; i < PWM_COUNT; i++)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving this to a private analogWriteOff (or something with a better name) function in cores/nRF5/wiring_analog_nRF5x.c?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than creating another function I could change analogWrite so that it turns off PWM when a duty cycle of zero is passed?

Its up to what you prefer as you are the owner and this affects the API. Either implementation is easy to implement.

@micooke
Copy link
Contributor Author

micooke commented Oct 6, 2017

Ok, can of worms officially opened 💥
nrf51 is done, but i noticed something i should have noticed earlier - the nRF52 only uses 3 out of 12 PWM channels. It has 3 PWM/TIMERS with 4 compare channels each, and in the core each compare channel output pin points to the same pin - so 3 outputs max (currently). This will need some work to fix it up, and luckily now i have the hardware to test it on!

@micooke
Copy link
Contributor Author

micooke commented Oct 6, 2017

Sorry i should have asked, @sandeepmistry , @dlabun - do you want me to fix the nRF52 PWM channel issue here or in a separate PR?

The two issues are somewhat linked in that to enable the extra pwm i need to add another parameter in the PWMContext structure, which will then require me to update how the TIMER/PWM modules are turned off.

@dlabun
Copy link
Collaborator

dlabun commented Oct 6, 2017

Sure, go for it.

}
else
{
digitalWrite(ulPin, LOW);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be HIGH - copy/paste error

}
else
{
digitalWrite(ulPin, LOW);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same copy/paste error again

…s with M channels each)

* replace static 8b resolution for nRF51 and nRF52 with user-defined up to 16b resolution
* enable 6x PWM signals for nRF51 (up from 3)
* enable 12x PWM signals for nRF52 (up from 3)
* disable / free-up PWM signals when ZERO is written as the analog value analogWrite(PIN, 0)
@micooke
Copy link
Contributor Author

micooke commented Oct 9, 2017

Update :

  • 6x analog/PWM signals enabled for nRF51 (up from 3)
  • 12x analog/PWM signals enabled for nRF52 (up from 3)

The nRF51 now uses TIMER2 as well as TIMER1. As i have said before, the softdevice uses TIMER0 so i didn't touch that.

The nRF5x documentation is lacking pretty severely compared to the AVR chips I have dealt with. Im very surprised but the implementation for the nRF51 uses software to set/clear the hardware pins. It also uses the first channel as the period interrupt, rather than having a separate overflow interrupt (which can be seen in the RBL core and several Nordic source code).

It basically looks like PWM is implemented rather poorly in the nRF51, and i guess that is the reason that the nRF52 has dedicated PWM channels.

@dlabun
Copy link
Collaborator

dlabun commented Feb 27, 2018

@micooke Any issues with merging this fix?

@sandeepmistry
Copy link
Owner

Let’s hold off on this one for a bit ...

@micooke
Copy link
Contributor Author

micooke commented May 9, 2018

Hi @sandeepmistry, is there an issue with this PR I haven't addressed or does it just need more testing?

@sandeepmistry
Copy link
Owner

@micooke @dlabun this one needs some more testing.

I'm concerned of the performance implications of calling analogWrite(pin, 0) for every digitalWrite(pin, value) call.

@micooke
Copy link
Contributor Author

micooke commented Aug 19, 2018

The idea for that was actually copied from the Arduino AVR core
https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring_analog.c#L112-L119

Which uses digitalWrite() if 0 or 255 are passed to analogWrite()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants