Dawn Framework 1.0
Universal data acquisition framework for embedded systems
pwm.cxx
1// dawn/src/io/pwm.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/io/pwm.hxx"
7
8#include <cstring>
9#include <new>
10
11using namespace dawn;
12
13int CIOPwm::configureDesc(const CDescObject &desc)
14{
16 size_t offset = 0;
17
18 for (size_t i = 0; i < desc.getSize(); i++)
19 {
20 item = desc.objectCfgItemAtOffset(offset);
21
22 switch (item->cfgid.s.cls)
23 {
25 {
26 offset += cfgCmnOffset(item);
27 break;
28 }
29
31 {
32 switch (item->cfgid.s.id)
33 {
34 case IO_PWM_CFG_FREQ:
35 {
36 if (item->cfgid.s.size != 1)
37 {
38 DAWNERR("invalid PWM frequency config size %d\n", item->cfgid.s.size);
39 return -EINVAL;
40 }
41
42 freq = *reinterpret_cast<const uint32_t *>(&item->data);
43 if (freq == 0)
44 {
45 DAWNERR("PWM frequency must be > 0\n");
46 return -EINVAL;
47 }
48
49 offset += item->cfgid.s.size + 1;
50 break;
51 }
52
53 default:
54 {
55 DAWNERR("Unsupported PWM config 0x%08" PRIx32 "\n", item->cfgid.v);
56 return -EINVAL;
57 }
58 }
59
60 break;
61 }
62
63 default:
64 {
65 DAWNERR("Unsupported PWM config 0x%08" PRIx32 "\n", item->cfgid.v);
66 return -EINVAL;
67 }
68 }
69 }
70
71 return OK;
72}
73
74CIOPwm::~CIOPwm()
75{
76 deinit();
77}
78
80{
81 int ret;
82 int i;
83
84 // Configure object
85
86 ret = configureDesc(getDesc());
87 if (ret != OK)
88 {
89 DAWNERR("PWM configure failed (error %d)\n", ret);
90 return ret;
91 }
92
93 // Get path to PWM
94
95 if (getCmnDevno() == -1)
96 {
97 DAWNERR("PWM device number not configured\n");
98 return -EINVAL;
99 }
100
101 snprintf(path, sizeof(path), PWM_PATH_FMT, getCmnDevno());
102
103 // Open file
104
105 fd = pwm_open(path);
106 if (fd < 0)
107 {
108 DAWNERR("failed to open file %d\n", -errno);
109 return -errno;
110 }
111
112 // Intialize gpi
113
114 pwm_init(fd);
115
116 // Allocate channels info
117
118 info = static_cast<dawn::porting::pwm_write_s *>(::operator new(
119 sizeof(dawn::porting::pwm_write_s) + channels * sizeof(info->channels[0]), std::nothrow));
120 if (info == nullptr)
121 {
122 DAWNERR("failed to allocate PWM channel info\n");
123 return -ENOMEM;
124 }
125
126 std::memset(info, 0, sizeof(dawn::porting::pwm_write_s) + channels * sizeof(info->channels[0]));
127
128 // Initialzie frequency for channels info which is constant
129
130 info->freq = freq;
131 for (i = 0; i < channels; i++)
132 {
133 info->channels[i].channel = i + 1;
134 }
135
136 return OK;
137}
138
140{
142 {
143 DAWNERR("PWM requires DTYPE_UINT32\n");
144 return -EINVAL;
145 }
146
147 return OK;
148}
149
151{
152 ::operator delete(info);
153 info = nullptr;
154
155 if (fd >= 0)
156 {
157 pwm_close(fd);
158 fd = -1;
159 }
160
161 return OK;
162}
163
165{
166 uint32_t *tmp = static_cast<uint32_t *>(data.getDataPtr());
167 int ret;
168
169 // Data dimmention must match PWM supported channels
170
171 if (data.getItems() < getDataDim())
172 {
173 return -EINVAL;
174 }
175
176 for (int i = 0; i < channels; i++)
177 {
178 // Valid data range is 0 to 1000 (0% - 100%)
179
180 if (tmp[i] > 1000)
181 {
182 return -EINVAL;
183 }
184
185 // channels start from 1
186 info->channels[i].duty = tmp[i];
187 info->channels[i].channel = i + 1;
188 }
189
190 // Write output
191
192 ret = pwm_write(fd, info);
193 if (ret < 0)
194 {
195 DAWNERR("pwm_write failed %d\n", ret);
196 return ret;
197 }
198
199#ifdef CONFIG_DAWN_IO_TIMESTAMP
200 if (isTimestamp())
201 {
202 ts = getTimestamp();
203 }
204#endif
205
206 return OK;
207}
208
210{
211 return pwm_start(fd);
212}
213
215{
216 return pwm_stop(fd);
217}
218
219int CIOPwm::trigger(uint8_t cmd)
220{
221 DAWNERR("CIOPwm::trigger not implemented\n");
222 return -ENOSYS;
223}
224
225int CIOPwm::onSetObjConfig(SObjectCfg::ObjectCfgId objcfg, uint32_t *data, size_t len)
226{
227 uint32_t oldFreq;
228 int ret;
229
231 {
232 return OK;
233 }
234
235 if (len != 1 || data == nullptr || data[0] == 0)
236 {
237 return -EINVAL;
238 }
239
240 if (info == nullptr)
241 {
242 freq = data[0];
243 return OK;
244 }
245
246 oldFreq = info->freq;
247 info->freq = data[0];
248
249 if (fd >= 0)
250 {
251 ret = pwm_write(fd, info);
252 if (ret < 0)
253 {
254 info->freq = oldFreq;
255 DAWNERR("pwm frequency update failed %d\n", ret);
256 return ret;
257 }
258 }
259
260 freq = data[0];
261 return OK;
262}
263
265{
266 return sizeof(uint32_t) * channels;
267}
268
269size_t CIOPwm::getDataDim() const
270{
271 return channels;
272}
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemAtOffset(size_t offset) const
Get configuration item at specified offset.
uint64_t getTimestamp()
Get current timestamp.
Definition common.cxx:194
bool isTimestamp() const
Check if I/O supports timestamp.
Definition common.cxx:189
int getCmnDevno() const
Get device number for this I/O.
Definition common.hxx:798
size_t cfgCmnOffset(const SObjectCfg::SObjectCfgItem *cfg)
Get offset of configuration item in descriptor.
Definition common.cxx:144
@ IO_CLASS_PWM
PWM output.
Definition common.hxx:172
@ IO_CLASS_ANY
Any I/O class.
Definition common.hxx:86
@ IO_PWM_CFG_FREQ
PWM frequency configuration.
Definition pwm.hxx:26
int configure()
Configure object from descriptor data.
Definition pwm.cxx:79
int init()
One-time initialize object after bindings are resolved.
Definition pwm.cxx:139
int setDataImpl(IODataCmn &data)
Set data implementation (override in derived classes).
Definition pwm.cxx:164
int onSetObjConfig(SObjectCfg::ObjectCfgId objcfg, uint32_t *data, size_t len)
Pre-update hook for runtime configuration writes.
Definition pwm.cxx:225
size_t getDataSize() const
Get data size in bytes.
Definition pwm.cxx:264
int doStart()
Start implementation hook.
Definition pwm.cxx:209
int deinit()
De-initialize object.
Definition pwm.cxx:150
int trigger(uint8_t cmd)
Execute a trigger command.
Definition pwm.cxx:219
int doStop()
Stop implementation hook.
Definition pwm.cxx:214
size_t getDataDim() const
Get data vector dimension.
Definition pwm.cxx:269
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
Definition objectcfg.hxx:60
static uint8_t objectCfgGetId(const ObjectCfgId objcfg)
Extract configuration identifier from ConfigID.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Base interface for I/O data buffers (static and dynamic).
Definition idata.hxx:21
virtual size_t getItems()=0
Get number of items per batch.
virtual void * getDataPtr(size_t batch=0)=0
Get pointer to data only (skips timestamp if present).
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
Definition objectid.hxx:96
PWM write data.
Definition pwm.hxx:22
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
Definition objectcfg.hxx:94
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.