Skip to content

Commit 38abc94

Browse files
committed
Use HwPWM ownership abstraction
1 parent fcce4da commit 38abc94

File tree

2 files changed

+50
-28
lines changed

2 files changed

+50
-28
lines changed

cores/nRF5/common_func.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
#define ADA_COUNTER __LINE__
7474
#endif
7575

76+
#include <inttypes.h>
77+
7678
#define COMMENT_OUT(x)
7779

7880
#define memclr(buffer, size) memset(buffer, 0, size)
@@ -170,6 +172,14 @@ const char* dbg_err_str(int32_t err_id); // TODO move to other place
170172
#define LOG_LV2_BUFFER(...)
171173
#endif
172174

175+
#if CFG_DEBUG >= 3
176+
#define LOG_LV3(...) ADALOG(__VA_ARGS__)
177+
#define LOG_LV3_BUFFER(...) ADALOG_BUFFER(__VA_ARGS__)
178+
#else
179+
#define LOG_LV3(...)
180+
#define LOG_LV3_BUFFER(...)
181+
#endif
182+
173183
#if CFG_DEBUG
174184

175185
#define PRINT_LOCATION() PRINTF("%s: %d:\n", __PRETTY_FUNCTION__, __LINE__)

cores/nRF5/wiring_analog.cpp

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include "Arduino.h"
3838

39+
3940
/* Implement analogWrite() and analogWriteResolution() using
4041
* HardwarePWM.
4142
*
@@ -45,18 +46,8 @@
4546
extern "C"
4647
{
4748

48-
class INTERNAL_ANALOG_STATE {
49-
public:
50-
uint8_t _lastAnalogWriteResolution = 8; // default value is 8-bit resolution (0..255)
51-
uint8_t _moduleUsedByAnalogWrites[HWPWM_MODULE_NUM];
52-
INTERNAL_ANALOG_STATE() : _lastAnalogWriteResolution(8) {
53-
for (int i = 0; i < HWPWM_MODULE_NUM; i++) {
54-
_moduleUsedByAnalogWrites[i] = 0;
55-
}
56-
}
57-
};
58-
59-
static INTERNAL_ANALOG_STATE _AnalogState;
49+
static uint8_t _lastAnalogWriteResolution;
50+
static const uintptr_t _token = (uintptr_t)(&_lastAnalogWriteResolution);
6051

6152
/**
6253
* This will apply to all PWM Hardware currently used by analogWrite(),
@@ -65,10 +56,10 @@ static INTERNAL_ANALOG_STATE _AnalogState;
6556
void analogWriteResolution( uint8_t res )
6657
{
6758
// save the resolution for when adding a new instance
68-
_AnalogState._lastAnalogWriteResolution = res;
59+
_lastAnalogWriteResolution = res;
6960
for (int i = 0; i<HWPWM_MODULE_NUM; i++)
7061
{
71-
if (!_AnalogState._moduleUsedByAnalogWrites[i]) continue;
62+
if (!HwPWMx[i]->isOwner(_token)) continue;
7263
HwPWMx[i]->setResolution(res);
7364
}
7465
}
@@ -82,26 +73,42 @@ void analogWriteResolution( uint8_t res )
8273
*/
8374
void analogWrite( uint32_t pin, uint32_t value )
8475
{
85-
// If the pin is already in use for analogWrite, this should be fast
86-
// If the pin is not already in use, then it's OK to take slightly more time to setup
76+
/* If the pin is already in use for analogWrite, this should be fast
77+
If the pin is not already in use, then it's OK to take slightly more time to setup
78+
*/
8779

88-
// first attempt to find the pin in any of the HWPWM modules used for analog writes
80+
// first, handle the case where the pin is already in use by analogWrite()
8981
for(int i=0; i<HWPWM_MODULE_NUM; i++)
9082
{
91-
if (!_AnalogState._moduleUsedByAnalogWrites[i]) continue;
83+
if (!HwPWMx[i]->isOwner(_token)) {
84+
LOG_LV3("ANA", "not currently owner of PWM %d", i);
85+
continue; // skip if not owner of this PWM instance
86+
}
87+
9288
int const ch = HwPWMx[i]->pin2channel(pin);
93-
if (ch < 0) continue; // pin not in use by the PWM instance
94-
// already in use by this PWM instance as channel ch ...
89+
if (ch < 0) {
90+
LOG_LV3("ANA", "pin %d is not used by PWM %d", pin, i);
91+
continue; // pin not in use by this PWM instance
92+
}
93+
LOG_LV2("ANA", "updating pin %" PRIu32 " used by PWM %d", pin, i);
9594
HwPWMx[i]->writeChannel(ch, value);
9695
return;
9796
}
9897

99-
// Next try adding only to those modules that are already in use
98+
// Next, handle the case where can add the pin to a PWM instance already owned by analogWrite()
10099
for(int i=0; i<HWPWM_MODULE_NUM; i++)
101100
{
102-
if (!_AnalogState._moduleUsedByAnalogWrites[i]) continue;
103-
if (!HwPWMx[i]->addPin(pin)) continue;
104-
// added to an already-used PWM instance, so write the value
101+
if (!HwPWMx[i]->isOwner(_token)) {
102+
LOG_LV3("ANA", "not currently owner of PWM %d", i);
103+
continue;
104+
}
105+
if (!HwPWMx[i]->addPin(pin)) {
106+
LOG_LV3("ANA", "could not add pin %" PRIu32 " to PWM %d", pin, i);
107+
continue;
108+
}
109+
110+
// successfully added the pin, so write the value also
111+
LOG_LV2("ANA", "Added pin %" PRIu32 " to already-owned PWM %d", pin, i);
105112
HwPWMx[i]->writePin(pin, value);
106113
return;
107114
}
@@ -111,11 +118,16 @@ void analogWrite( uint32_t pin, uint32_t value )
111118
// 2. it currently has no pins in use.
112119
for(int i=0; i<HWPWM_MODULE_NUM; i++)
113120
{
114-
if (_AnalogState._moduleUsedByAnalogWrites[i]) continue;
115-
if (HwPWMx[i]->usedChannelCount() != 0) continue;
116-
// added to an already-used PWM instance, so write the value
117-
HwPWMx[i]->setResolution(_AnalogState._lastAnalogWriteResolution);
121+
if (!HwPWMx[i]->takeOwnership(_token)) {
122+
LOG_LV3("ANA", "Could not take ownership of PWM %d", i);
123+
continue;
124+
}
125+
126+
// apply the cached analog resolution to newly owned instances
127+
HwPWMx[i]->setResolution(_lastAnalogWriteResolution);
128+
HwPWMx[i]->addPin(pin);
118129
HwPWMx[i]->writePin(pin, value);
130+
LOG_LV2("ANA", "took ownership of, and added pin %" PRIu32 " to, PWM %d", pin, i);
119131
return;
120132
}
121133

0 commit comments

Comments
 (0)