Skip to content

Commit 14b44a5

Browse files
committed
Merge branch 'develop'
2 parents 8e80282 + 04c45e1 commit 14b44a5

File tree

3 files changed

+62
-71
lines changed

3 files changed

+62
-71
lines changed

cores/nRF5/HardwarePWM.cpp

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ HardwarePWM* HwPWMx[] =
5656
HardwarePWM::HardwarePWM(NRF_PWM_Type* pwm)
5757
{
5858
_pwm = pwm;
59-
60-
_count = 0;
6159
arrclr(_seq0);
6260

6361
_max_value = 255;
6462
_clock_div = PWM_PRESCALER_PRESCALER_DIV_1; // 16 Mhz
63+
64+
// FIXME workaround to fix bootloader 0.2.6 does not clean up PSEL[1] of PWM0
65+
_pwm->PSEL.OUT[1] = 0xFFFFFFFFUL;
6566
}
6667

6768
void HardwarePWM::setResolution(uint8_t bitnum)
@@ -88,19 +89,21 @@ void HardwarePWM::setClockDiv(uint8_t div)
8889
*/
8990
bool HardwarePWM::addPin(uint8_t pin)
9091
{
91-
VERIFY( _count <= MAX_CHANNELS );
92+
// succeed if pin is already configured
93+
if ( pin2channel(pin) >= 0 ) return true;
9294

93-
// Check if pin is already configured
94-
for(uint8_t i=0; i<_count; i++)
95-
{
96-
if (_pwm->PSEL.OUT[i] == pin) return true;
97-
}
95+
int ch = -1;
9896

99-
if ((_count >= MAX_CHANNELS))
97+
// find free slot which is not connected
98+
for(int i=0; i<MAX_CHANNELS; i++)
10099
{
101-
//Pin not already configured, but this HardwarePWM is full
102-
return false;
100+
if ( _pwm->PSEL.OUT[i] & PWM_PSEL_OUT_CONNECT_Msk )
101+
{
102+
ch = i;
103+
break;
104+
}
103105
}
106+
VERIFY ( ch >= 0 );
104107

105108
pinMode(pin, OUTPUT);
106109
digitalWrite(pin, LOW);
@@ -109,17 +112,35 @@ bool HardwarePWM::addPin(uint8_t pin)
109112
if ( enabled() )
110113
{
111114
_pwm->ENABLE = 0;
112-
_pwm->PSEL.OUT[_count++] = g_ADigitalPinMap[pin];
115+
_pwm->PSEL.OUT[ch] = g_ADigitalPinMap[pin];
113116
_pwm->ENABLE = 1;
114117
_start();
115118
}else
116119
{
117-
_pwm->PSEL.OUT[_count++] = g_ADigitalPinMap[pin];
120+
_pwm->PSEL.OUT[ch] = g_ADigitalPinMap[pin];
118121
}
119122

120123
return true;
121124
}
122125

126+
bool HardwarePWM::removePin(uint8_t pin)
127+
{
128+
int ch = pin2channel(pin);
129+
VERIFY( ch >= 0 );
130+
131+
bool const en = enabled();
132+
133+
// Must disable before changing PSEL
134+
if ( en ) _pwm->ENABLE = 0;
135+
136+
_pwm->PSEL.OUT[ch] = 0xFFFFFFFFUL;
137+
_seq0[ch] = 0;
138+
139+
if ( en ) _pwm->ENABLE = 1;
140+
141+
return true;
142+
}
143+
123144
bool HardwarePWM::enabled (void)
124145
{
125146
return _pwm->ENABLE;
@@ -163,7 +184,7 @@ void HardwarePWM::stop(void)
163184

164185
bool HardwarePWM::writeChannel(uint8_t ch, uint16_t value, bool inverted )
165186
{
166-
VERIFY( ch < _count );
187+
VERIFY( ch < MAX_CHANNELS );
167188

168189
_seq0[ch] = value | (inverted ? 0 : bit(15));
169190

cores/nRF5/HardwarePWM.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ class HardwarePWM
5151
enum { MAX_CHANNELS = 4 }; // Max channel per group
5252
NRF_PWM_Type* _pwm;
5353

54-
uint8_t _count;
5554
uint16_t _seq0[MAX_CHANNELS];
5655

5756
uint16_t _max_value;
@@ -69,9 +68,12 @@ class HardwarePWM
6968
void setClockDiv(uint8_t div); // value is PWM_PRESCALER_PRESCALER_DIV_x, DIV1 is 16Mhz
7069

7170
bool addPin (uint8_t pin);
71+
bool removePin (uint8_t pin);
72+
7273
int pin2channel(uint8_t pin)
7374
{
74-
for(int i=0; i<_count; i++)
75+
pin = g_ADigitalPinMap[pin];
76+
for(int i=0; i<MAX_CHANNELS; i++)
7577
{
7678
if ( _pwm->PSEL.OUT[i] == pin ) return i;
7779
}

libraries/Bluefruit52Lib/examples/Hardware/hwpwm/hwpwm.ino

Lines changed: 23 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,39 @@
1313
*********************************************************************/
1414

1515
/*
16-
* This sketch use all 12 channels of 3 Hardware PWM.
17-
* Also change the resolution to max 15-bit.
18-
* Each PWM Hardware group (4 pin) also run with different frequency
16+
* This sketch use different Hardware PWMs for LED Blue and Red
17+
* running with different frequency
1918
* - PWM0 : clock/1 ~ 16Mhz
20-
* - PWM1 : clock/4 ~ 4Mhz
21-
* - PMW2 : clock/16 ~ 1Mhz
22-
*
23-
* Since LED RED and BLUE are on different Hardware PWM,
24-
* LED BLUE will blink (due to lower freq) while fading while LED RED
25-
* looks more solid. Furthermore LED RED group write value (PWM1) is inverted
19+
* - PWM1 : clock/16 ~ 1Mhz
20+
*
21+
* While LED RED looks solid, LED BLUE will blink while fading
22+
* (due to its lower freq). Furthermore LED RED is inverted
2623
* compared to LED BLUE (PWM2) --> They fade in opposite direction.
2724
*/
2825

2926
#include <Arduino.h>
3027

31-
// Maximum 12 pins can be used for 3 PWM modules ( 4 channel each )
32-
// Note: nRF52832 has 3 PWM modules, nRF52840 has 4 PWM modules
33-
int pins[12] =
34-
{
35-
A0 , A1 , A2 , A3,
36-
A4 , A5 , A6 , LED_RED, /* avoid A7 (VBAT) */
37-
27 , LED_BLUE, PIN_WIRE_SDA, PIN_WIRE_SCL
38-
};
39-
4028
/**************************************************************************/
4129
/*!
4230
@brief The setup function runs once when reset the board
4331
*/
4432
/**************************************************************************/
4533
void setup()
46-
{
47-
// Add 4 pins into a group
48-
// It is better to add Pin before call .begin()
49-
for (int i=0; i<12; i++)
50-
{
51-
HwPWMx[i/4]->addPin( pins[i] );
52-
}
34+
{
35+
// Add LED RED to PWM0
36+
HwPWM0.addPin( LED_RED );
37+
38+
// Add LED BLUE to PWM1
39+
HwPWM1.addPin( LED_BLUE );
5340

54-
// Enable all 3 PWM modules with 15-bit resolutions(max) but different clock div
41+
// Enable PWM modules with 15-bit resolutions(max) but different clock div
5542
HwPWM0.begin();
5643
HwPWM0.setResolution(15);
57-
HwPWM0.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_1); // default : freq = 16Mhz
44+
HwPWM0.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_1); // freq = 16Mhz
5845

5946
HwPWM1.begin();
6047
HwPWM1.setResolution(15);
61-
HwPWM1.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_4); // default : freq = 4Mhz
62-
63-
HwPWM2.begin();
64-
HwPWM2.setResolution(15);
65-
HwPWM2.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_16); // default : freq = 1Mhz
48+
HwPWM1.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_16); // freq = 1Mhz
6649
}
6750

6851
/**************************************************************************/
@@ -73,39 +56,24 @@ void setup()
7356
void loop()
7457
{
7558
const int maxValue = bit(15) - 1;
76-
bool inverted;
7759

7860
// fade in from min to max
79-
// inverted PWM0 (false), PWM1 (true), PWM2 (false)
8061
for (int fadeValue = 0 ; fadeValue <= maxValue; fadeValue += 1024)
8162
{
82-
inverted = false;
83-
84-
for (int i=0; i<12; i++)
85-
{
86-
// Inverted for each PWM group
87-
if (i%4) inverted = !inverted;
88-
89-
HwPWMx[i/4]->writePin( pins[i], fadeValue, inverted);
90-
}
91-
63+
// Write same value but inverted for Led Blue
64+
HwPWM0.writePin(LED_RED, fadeValue, false);
65+
HwPWM1.writePin(LED_BLUE, fadeValue, true);
66+
9267
// wait for 30 milliseconds to see the dimming effect
9368
delay(30);
9469
}
9570

9671
// fade out from max to min
97-
// inverted PWM0 (false), PWM1 (true), PWM2 (false)
9872
for (int fadeValue = maxValue ; fadeValue >= 0; fadeValue -= 1024)
99-
{
100-
inverted = false;
101-
102-
for (int i=0; i<12; i++)
103-
{
104-
// Inverted for each PWM group
105-
if (i%4) inverted = !inverted;
106-
107-
HwPWMx[i/4]->writePin( pins[i], fadeValue, inverted);
108-
}
73+
{
74+
// Write same value but inverted for Led Blue
75+
HwPWM0.writePin(LED_RED, fadeValue, false);
76+
HwPWM1.writePin(LED_BLUE, fadeValue, true);
10977

11078
// wait for 30 milliseconds to see the dimming effect
11179
delay(30);

0 commit comments

Comments
 (0)