-
-
Notifications
You must be signed in to change notification settings - Fork 279
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
base: master
Are you sure you want to change the base?
Conversation
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
Tidy-up of #193 |
There was a problem hiding this 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!
cores/nRF5/wiring_analog_nRF51.c
Outdated
} | ||
} | ||
|
||
// fallback to digitalWrite if no available PWM channel | ||
if (ulValue < 128) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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
cores/nRF5/wiring_digital.c
Outdated
@@ -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++) |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
Ok, can of worms officially opened 💥 |
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. |
Sure, go for it. |
cores/nRF5/wiring_analog_nRF51.c
Outdated
} | ||
else | ||
{ | ||
digitalWrite(ulPin, LOW); |
There was a problem hiding this comment.
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
cores/nRF5/wiring_analog_nRF52.c
Outdated
} | ||
else | ||
{ | ||
digitalWrite(ulPin, LOW); |
There was a problem hiding this comment.
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)
Update :
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. |
@micooke Any issues with merging this fix? |
Let’s hold off on this one for a bit ... |
Hi @sandeepmistry, is there an issue with this PR I haven't addressed or does it just need more testing? |
The idea for that was actually copied from the Arduino AVR core Which uses |
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