Skip to content

Commit 97be20a

Browse files
committed
Start! And added to hardware.cpp
1 parent 8c68d45 commit 97be20a

File tree

8 files changed

+385
-1
lines changed

8 files changed

+385
-1
lines changed

src/Wippersnapper_V2.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Wippersnapper_V2::Wippersnapper_V2() {
5555
WsV2._ds18x20_controller = new DS18X20Controller();
5656
WsV2._i2c_controller = new I2cController();
5757
WsV2._pixels_controller = new PixelsController();
58+
WsV2._pwm_controller = new PWMController();
5859
};
5960

6061
/**************************************************************************/
@@ -431,6 +432,41 @@ bool cbDecodeBrokerToDevice(pb_istream_t *stream, const pb_field_t *field,
431432
return false;
432433
}
433434
break;
435+
case wippersnapper_signal_BrokerToDevice_pwm_add_tag:
436+
WS_DEBUG_PRINTLN("-> PWM Add Message Type");
437+
if (!WsV2._pwm_controller->Handle_PWM_Add(stream)) {
438+
WS_DEBUG_PRINTLN("ERROR: Unable to add PWM pin!");
439+
return false;
440+
}
441+
break;
442+
case wippersnapper_signal_BrokerToDevice_pwm_write_duty_cycle_tag:
443+
WS_DEBUG_PRINTLN("-> PWM Write Duty Cycle Message Type");
444+
if (!WsV2._pwm_controller->Handle_PWM_Write_DutyCycle(stream)) {
445+
WS_DEBUG_PRINTLN("ERROR: Unable to write duty cycle to PWM pin!");
446+
return false;
447+
}
448+
break;
449+
case wippersnapper_signal_BrokerToDevice_pwm_write_duty_cycle_multi_tag:
450+
WS_DEBUG_PRINTLN("-> PWM Write Duty Cycle Multi Message Type");
451+
if (!WsV2._pwm_controller->Handle_PWM_Write_DutyCycle_Multi(stream)) {
452+
WS_DEBUG_PRINTLN("ERROR: Unable to write multi duty cycle to PWM pins!");
453+
return false;
454+
}
455+
break;
456+
case wippersnapper_signal_BrokerToDevice_pwm_write_frequency_tag:
457+
WS_DEBUG_PRINTLN("-> PWM Write Frequency Message Type");
458+
if (!WsV2._pwm_controller->Handle_PWM_Write_Frequency(stream)) {
459+
WS_DEBUG_PRINTLN("ERROR: Unable to write frequency to PWM pin!");
460+
return false;
461+
}
462+
break;
463+
case wippersnapper_signal_BrokerToDevice_pwm_remove_tag:
464+
WS_DEBUG_PRINTLN("-> PWM Remove Message Type");
465+
if (!WsV2._pwm_controller->Handle_PWM_Remove(stream)) {
466+
WS_DEBUG_PRINTLN("ERROR: Unable to remove PWM pin!");
467+
return false;
468+
}
469+
break;
434470
default:
435471
WS_DEBUG_PRINTLN("ERROR: BrokerToDevice message type not found!");
436472
return false;

src/Wippersnapper_V2.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
#include "protos/digitalio.pb.h"
8989
#include "protos/ds18x20.pb.h"
9090
#include "protos/pixels.pb.h"
91+
#include "protos/pwm.pb.h"
9192
#include "protos/signal.pb.h"
9293

9394
// External libraries
@@ -112,6 +113,7 @@
112113
#include "components/ds18x20/controller.h"
113114
#include "components/i2c/controller.h"
114115
#include "components/pixels/controller.h"
116+
#include "components/pwm/controller.h"
115117
#include "components/sensor/model.h"
116118

117119
// Display
@@ -153,6 +155,7 @@ class AnalogIOController;
153155
class DS18X20Controller;
154156
class I2cController;
155157
class PixelsController;
158+
class PWMController;
156159

157160
/**************************************************************************/
158161
/*!
@@ -255,7 +258,8 @@ class Wippersnapper_V2 {
255258
nullptr; ///< Instance of DS18X20 controller
256259
I2cController *_i2c_controller = nullptr; ///< Instance of I2C controller
257260
PixelsController *_pixels_controller =
258-
nullptr; ///< Instance of Pixels controller
261+
nullptr; ///< Instance of Pixels controller
262+
PWMController *_pwm_controller = nullptr; ///< Instance of PWM controller
259263

260264
// TODO: does this really need to be global?
261265
uint8_t _macAddrV2[6]; /*!< Unique network iface identifier */

src/components/pwm/controller.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*!
2+
* @file src/components/pwm/controller.cpp
3+
*
4+
* Controller for the pwm API
5+
*
6+
* Adafruit invests time and resources providing this open source code,
7+
* please support Adafruit and open-source hardware by purchasing
8+
* products from Adafruit!
9+
*
10+
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+
*
12+
* BSD license, all text here must be included in any redistribution.
13+
*
14+
*/
15+
#include "controller.h"
16+
17+
PWMController::PWMController() {
18+
_pwm_model = new PWMModel();
19+
_pwm_hardware = new PWMHardware();
20+
}
21+
22+
PWMController::~PWMController() {
23+
delete _pwm_model;
24+
delete _pwm_hardware;
25+
}
26+
27+
bool PWMController::Handle_PWM_Add(pb_istream_t *stream) { return false; }
28+
29+
bool PWMController::Handle_PWM_Write_DutyCycle(pb_istream_t *stream) {
30+
return false;
31+
}
32+
33+
bool PWMController::Handle_PWM_Write_DutyCycle_Multi(pb_istream_t *stream) {
34+
return false;
35+
}
36+
37+
bool PWMController::Handle_PWM_Write_Frequency(pb_istream_t *stream) {
38+
return false;
39+
}
40+
41+
bool PWMController::Handle_PWM_Remove(pb_istream_t *stream) { return false; }

src/components/pwm/controller.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*!
2+
* @file src/components/pwm/controller.h
3+
*
4+
* Controller for the pwm API
5+
*
6+
* Adafruit invests time and resources providing this open source code,
7+
* please support Adafruit and open-source hardware by purchasing
8+
* products from Adafruit!
9+
*
10+
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+
*
12+
* BSD license, all text here must be included in any redistribution.
13+
*
14+
*/
15+
#ifndef WS_PWM_CONTROLLER_H
16+
#define WS_PWM_CONTROLLER_H
17+
#include "Wippersnapper_V2.h"
18+
#include "hardware.h"
19+
#include "model.h"
20+
21+
class Wippersnapper_V2; // Forward declaration
22+
class PWMModel; // Forward declaration
23+
class PWMHardware; // Forward declaration
24+
25+
/**************************************************************************/
26+
/*!
27+
@brief Routes messages using the pwm.proto API to the
28+
appropriate hardware and model classes, controls and tracks
29+
the state of the hardware's PWM pins.
30+
*/
31+
/**************************************************************************/
32+
class PWMController {
33+
public:
34+
PWMController();
35+
~PWMController();
36+
// Called by the cbDecodeBrokerToDevice router function
37+
bool Handle_PWM_Add(pb_istream_t *stream);
38+
bool Handle_PWM_Write_DutyCycle(pb_istream_t *stream);
39+
bool Handle_PWM_Write_DutyCycle_Multi(pb_istream_t *stream);
40+
bool Handle_PWM_Write_Frequency(pb_istream_t *stream);
41+
bool Handle_PWM_Remove(pb_istream_t *stream);
42+
43+
private:
44+
PWMModel *_pwm_model;
45+
PWMHardware *_pwm_hardware;
46+
};
47+
extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance
48+
#endif // WS_PWM_CONTROLLER_H

src/components/pwm/hardware.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*!
2+
* @file src/components/pwm/hardware.cpp
3+
*
4+
* Hardware for the pwm.proto message.
5+
*
6+
* Adafruit invests time and resources providing this open source code,
7+
* please support Adafruit and open-source hardware by purchasing
8+
* products from Adafruit!
9+
*
10+
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+
*
12+
* BSD license, all text here must be included in any redistribution.
13+
*
14+
*/
15+
#include "hardware.h"
16+
17+
PWMHardware::PWMHardware() {
18+
_is_attached = false;
19+
}
20+
21+
PWMHardware::~PWMHardware() {
22+
if (_is_attached)
23+
DetachPin();
24+
}
25+
26+
bool PWMHardware::AttachPin(uint8_t pin, uint32_t frequency, uint32_t resolution) {
27+
#ifdef ARDUINO_ARCH_ESP32
28+
_is_attached = ledcAttach(_pin, _frequency, _resolution);
29+
#else
30+
_is_attached = true;
31+
#endif
32+
33+
if (_is_attached) {
34+
_pin = pin;
35+
_frequency = frequency;
36+
_resolution = resolution;
37+
_duty_cycle = 0;
38+
}
39+
40+
return _is_attached;
41+
}
42+
43+
bool PWMHardware::DetachPin() {
44+
if (! _is_attached) {
45+
WS_DEBUG_PRINTLN("[pwm] Pin not attached!");
46+
return false;
47+
}
48+
bool did_detach = false;
49+
#ifdef ARDUINO_ARCH_ESP32
50+
did_detach = ledcDetach(_pin);
51+
#else
52+
did_detach = true;
53+
#endif
54+
55+
// "Disable" the pin's output
56+
digitalWrite(_pin, LOW);
57+
}
58+
59+
bool PWMHardware::WriteDutyCycle(uint32_t duty) {
60+
if (! _is_attached) {
61+
WS_DEBUG_PRINTLN("[pwm] Pin not attached!");
62+
return false;
63+
}
64+
bool did_write = false;
65+
#ifdef defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) && defined(STATUS_LED_PIN)
66+
// Adafruit Feather ESP8266's analogWrite() gets inverted since the builtin
67+
// LED is reverse-wired
68+
_duty_cycle = 255 - duty;
69+
#else
70+
_duty_cycle = duty;
71+
#endif
72+
73+
#ifdef ARDUINO_ARCH_ESP32
74+
did_write = analogWrite(_duty_cycle);
75+
#else
76+
analogWrite(_pin, duty);
77+
did_write = true;
78+
#endif
79+
80+
return true;
81+
}
82+
83+
// LEDC API Wrappers
84+
#ifdef ARDUINO_ARCH_ESP32
85+
bool PWMHardware::analogWrite(uint32_t value) {
86+
// clamp
87+
if (value > 255 || value < 0) {
88+
WS_DEBUG_PRINTLN("[pwm] Value out of range!");
89+
return false;
90+
}
91+
92+
// Calculate duty cycle for the `value` passed in
93+
// (assumes 12-bit resolution, 2^12)
94+
uint32_t dutyCycle = (uint32_t)((4095.0 / 255.0) * min(value, (uint32_t)255));
95+
return ledcWrite(_pin, dutyCycle);
96+
}
97+
98+
#endif // ARDUINO_ARCH_ESP32

src/components/pwm/hardware.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*!
2+
* @file src/components/pwm/hardware.h
3+
*
4+
* Hardware for the pwm.proto message.
5+
*
6+
* Adafruit invests time and resources providing this open source code,
7+
* please support Adafruit and open-source hardware by purchasing
8+
* products from Adafruit!
9+
*
10+
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+
*
12+
* BSD license, all text here must be included in any redistribution.
13+
*
14+
*/
15+
#ifndef WS_PWM_HARDWARE_H
16+
#define WS_PWM_HARDWARE_H
17+
#include "Wippersnapper_V2.h"
18+
#ifdef ARDUINO_ARCH_ESP32
19+
#include "esp32-hal-ledc.h"
20+
#include "esp_err.h"
21+
#endif
22+
23+
/**************************************************************************/
24+
/*!
25+
@brief Interface for interacting with hardware's PWM API.
26+
*/
27+
/**************************************************************************/
28+
class PWMHardware {
29+
public:
30+
PWMHardware();
31+
~PWMHardware();
32+
bool AttachPin(uint8_t pin, uint32_t frequency, uint32_t resolution);
33+
bool DetachPin();
34+
bool WriteDutyCycle(uint32_t duty);
35+
36+
// Abstractions for LEDC API
37+
#ifdef ARDUINO_ARCH_ESP32
38+
bool analogWrite(uint32_t value);
39+
#endif
40+
private:
41+
bool _is_attached;
42+
uint8_t _pin;
43+
uint32_t _frequency;
44+
uint32_t _resolution;
45+
uint32_t _duty_cycle;
46+
};
47+
#endif // WS_PWM_HARDWARE_H

src/components/pwm/model.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*!
2+
* @file src/components/pwm/model.cpp
3+
*
4+
* Model for the pwm.proto message.
5+
*
6+
* Adafruit invests time and resources providing this open source code,
7+
* please support Adafruit and open-source hardware by purchasing
8+
* products from Adafruit!
9+
*
10+
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+
*
12+
* BSD license, all text here must be included in any redistribution.
13+
*
14+
*/
15+
#include "model.h"
16+
17+
PWMModel::PWMModel() {}
18+
19+
PWMModel::~PWMModel() {}
20+
21+
bool PWMModel::DecodePWMAdd(pb_istream_t *stream) {
22+
return false;
23+
}
24+
25+
wippersnapper_pwm_PWMAdd *PWMModel::GetPWMAddMsg() {
26+
}
27+
28+
bool PWMModel::EncodePWMAdded(char *pin_name, bool did_attach) {
29+
return false;
30+
}
31+
32+
wippersnapper_pwm_PWMAdded *PWMModel::GetPWMAddedMsg() {
33+
}
34+
35+
bool PWMModel::DecodePWMRemove(pb_istream_t *stream) {
36+
return false;
37+
}
38+
39+
wippersnapper_pwm_PWMRemove *PWMModel::GetPWMRemoveMsg() {
40+
}
41+
42+
bool PWMModel::DecodePWMWriteDutyCycle(pb_istream_t *stream) {
43+
return false;
44+
}
45+
46+
wippersnapper_pwm_PWMWriteDutyCycle *PWMModel::GetPWMWriteDutyCycleMsg() {
47+
}
48+
49+
bool PWMModel::DecodePWMWriteDutyCycleMulti(pb_istream_t *stream) {
50+
return false;
51+
}
52+
53+
wippersnapper_pwm_PWMWriteDutyCycleMulti *PWMModel::GetPWMWriteDutyCycleMultiMsg() {
54+
}
55+
56+
bool PWMModel::DecodePWMWriteFrequency(pb_istream_t *stream) {
57+
return false;
58+
}
59+
60+
wippersnapper_pwm_PWMWriteFrequency *PWMModel::GetPWMWriteFrequencyMsg() {
61+
}

0 commit comments

Comments
 (0)