36
36
37
37
#include " Arduino.h"
38
38
39
+
39
40
/* Implement analogWrite() and analogWriteResolution() using
40
41
* HardwarePWM.
41
42
*
45
46
extern " C"
46
47
{
47
48
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);
60
51
61
52
/* *
62
53
* This will apply to all PWM Hardware currently used by analogWrite(),
@@ -65,10 +56,10 @@ static INTERNAL_ANALOG_STATE _AnalogState;
65
56
void analogWriteResolution ( uint8_t res )
66
57
{
67
58
// save the resolution for when adding a new instance
68
- _AnalogState. _lastAnalogWriteResolution = res;
59
+ _lastAnalogWriteResolution = res;
69
60
for (int i = 0 ; i<HWPWM_MODULE_NUM; i++)
70
61
{
71
- if (!_AnalogState. _moduleUsedByAnalogWrites [i]) continue ;
62
+ if (!HwPWMx [i]-> isOwner (_token) ) continue ;
72
63
HwPWMx[i]->setResolution (res);
73
64
}
74
65
}
@@ -82,26 +73,42 @@ void analogWriteResolution( uint8_t res )
82
73
*/
83
74
void analogWrite ( uint32_t pin, uint32_t value )
84
75
{
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
+ */
87
79
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()
89
81
for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
90
82
{
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
+
92
88
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);
95
94
HwPWMx[i]->writeChannel (ch, value);
96
95
return ;
97
96
}
98
97
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()
100
99
for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
101
100
{
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);
105
112
HwPWMx[i]->writePin (pin, value);
106
113
return ;
107
114
}
@@ -111,11 +118,16 @@ void analogWrite( uint32_t pin, uint32_t value )
111
118
// 2. it currently has no pins in use.
112
119
for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
113
120
{
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);
118
129
HwPWMx[i]->writePin (pin, value);
130
+ LOG_LV2 (" ANA" , " took ownership of, and added pin %" PRIu32 " to, PWM %d" , pin, i);
119
131
return ;
120
132
}
121
133
0 commit comments