45
45
extern " C"
46
46
{
47
47
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;
60
+
48
61
/* *
49
- * This will apply to all PWM Hardware
62
+ * This will apply to all PWM Hardware currently used by analogWrite(),
63
+ * and automatically apply to future calls to analogWrite().
50
64
*/
51
65
void analogWriteResolution ( uint8_t res )
52
66
{
67
+ // save the resolution for when adding a new instance
68
+ _AnalogState._lastAnalogWriteResolution = res;
53
69
for (int i = 0 ; i<HWPWM_MODULE_NUM; i++)
54
70
{
71
+ if (!_AnalogState._moduleUsedByAnalogWrites [i]) continue ;
55
72
HwPWMx[i]->setResolution (res);
56
73
}
57
74
}
@@ -65,17 +82,50 @@ void analogWriteResolution( uint8_t res )
65
82
*/
66
83
void analogWrite ( uint32_t pin, uint32_t value )
67
84
{
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
87
+
88
+ // first attempt to find the pin in any of the HWPWM modules used for analog writes
68
89
for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
69
90
{
70
- // Added by if needed
71
- if ( HwPWMx[i]->addPin (pin) )
72
- {
73
- HwPWMx[i]-> writePin (pin, value);
74
- return ;
75
- }
91
+ if (!_AnalogState. _moduleUsedByAnalogWrites [i]) continue ;
92
+ 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 ...
95
+ HwPWMx[i]-> writeChannel (ch, value) ;
96
+ return ;
76
97
}
77
- }
78
98
99
+ // Next try adding only to those modules that are already in use
100
+ for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
101
+ {
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
105
+ HwPWMx[i]->writePin (pin, value);
106
+ return ;
107
+ }
108
+
109
+ // Attempt to acquire a new HwPWMx instance ... but only where
110
+ // 1. it's not one already used for analog, and
111
+ // 2. it currently has no pins in use.
112
+ for (int i=0 ; i<HWPWM_MODULE_NUM; i++)
113
+ {
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 );
118
+ HwPWMx[i]->writePin (pin, value);
119
+ return ;
120
+ }
121
+
122
+ // failed to allocate a HwPWM instance.
123
+ // output appropriate debug message.
124
+ LOG_LV1 (" ANA" , " Unable to find a free PWM peripheral" );
125
+ // TODO: Add additional diagnostics to function at higher log levels
126
+ return ;
79
127
}
80
128
129
+ } // end extern "C"
130
+
81
131
0 commit comments