ws2812 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,311 @@
1
+ /*
2
+ Copyright (c) 2012, Broadcom Europe Ltd.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ * Neither the name of the copyright holder nor the
13
+ names of its contributors may be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include <stdio.h>
29
+ #include <string.h>
30
+ #include <stdlib.h>
31
+ #include <fcntl.h>
32
+ #include <unistd.h>
33
+ #include <assert.h>
34
+ #include <stdint.h>
35
+ #include <errno.h>
36
+ #include <sys/mman.h>
37
+ #include <sys/ioctl.h>
38
+ #include <sys/types.h>
39
+ #include <sys/stat.h>
40
+
41
+ #include "mailbox.h"
42
+
43
+ //#define DEBUG
44
+
45
+ #define PAGE_SIZE (4*1024)
46
+
47
+ void *mapmem(unsigned base, unsigned size)
48
+ {
49
+ int mem_fd;
50
+ unsigned offset = base % PAGE_SIZE;
51
+ base = base - offset;
52
+ /* open /dev/mem */
53
+ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
54
+ printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n");
55
+ exit (-1);
56
+ }
57
+ void *mem = mmap(
58
+ 0,
59
+ size,
60
+ PROT_READ|PROT_WRITE,
61
+ MAP_SHARED/*|MAP_FIXED*/,
62
+ mem_fd,
63
+ base);
64
+ #ifdef DEBUG
65
+ printf("base=0x%x, mem=%p\n", base, mem);
66
+ #endif
67
+ if (mem == MAP_FAILED) {
68
+ printf("mmap error %d\n", (int)mem);
69
+ exit (-1);
70
+ }
71
+ close(mem_fd);
72
+ return (char *)mem + offset;
73
+ }
74
+
75
+ void *unmapmem(void *addr, unsigned size)
76
+ {
77
+ unsigned offset = (unsigned)addr % PAGE_SIZE;
78
+ addr = addr - offset;
79
+ int s = munmap(addr, size);
80
+ if (s != 0) {
81
+ printf("munmap error %d\n", s);
82
+ exit (-1);
83
+ }
84
+
85
+ return NULL;
86
+ }
87
+
88
+ /*
89
+ * use ioctl to send mbox property message
90
+ */
91
+
92
+ static int mbox_property(int file_desc, void *buf)
93
+ {
94
+ int fd = file_desc;
95
+ int ret_val = -1;
96
+
97
+ if (fd < 0) {
98
+ fd = mbox_open();
99
+ }
100
+ if (fd >= 0) {
101
+ ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf);
102
+
103
+ if (ret_val < 0) {
104
+ // printf("ioctl_set_msg failed, errno %d: %m\n", errno);
105
+ // XXX: this is apparently the only error, so why would we bother anyone?
106
+ }
107
+ }
108
+ #ifdef DEBUG
109
+ unsigned *p = buf; int i; unsigned size = *(unsigned *)buf;
110
+ for (i=0; i<size/4; i++)
111
+ printf("%04x: 0x%08x\n", i*sizeof *p, p[i]);
112
+ #endif
113
+ if (file_desc < 0)
114
+ mbox_close(fd);
115
+
116
+ return ret_val;
117
+ }
118
+
119
+ unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags)
120
+ {
121
+ int i=0;
122
+ unsigned p[32];
123
+
124
+ #ifdef DEBUG
125
+ printf("Requesting %d bytes\n", size);
126
+ #endif
127
+ p[i++] = 0; // size
128
+ p[i++] = 0x00000000; // process request
129
+
130
+ p[i++] = 0x3000c; // (the tag id)
131
+ p[i++] = 12; // (size of the buffer)
132
+ p[i++] = 12; // (size of the data)
133
+ p[i++] = size; // (num bytes? or pages?)
134
+ p[i++] = align; // (alignment)
135
+ p[i++] = flags; // (MEM_FLAG_L1_NONALLOCATING)
136
+
137
+ p[i++] = 0x00000000; // end tag
138
+ p[0] = i*sizeof *p; // actual size
139
+
140
+ if (mbox_property(file_desc, p) < 0)
141
+ return -1;
142
+ else
143
+ return p[5];
144
+ }
145
+
146
+ unsigned mem_free(int file_desc, unsigned handle)
147
+ {
148
+ int i=0;
149
+ unsigned p[32];
150
+ p[i++] = 0; // size
151
+ p[i++] = 0x00000000; // process request
152
+
153
+ p[i++] = 0x3000f; // (the tag id)
154
+ p[i++] = 4; // (size of the buffer)
155
+ p[i++] = 4; // (size of the data)
156
+ p[i++] = handle;
157
+
158
+ p[i++] = 0x00000000; // end tag
159
+ p[0] = i*sizeof *p; // actual size
160
+
161
+ mbox_property(file_desc, p);
162
+ return p[5];
163
+ }
164
+
165
+ unsigned mem_lock(int file_desc, unsigned handle)
166
+ {
167
+ int i=0;
168
+ unsigned p[32];
169
+ p[i++] = 0; // size
170
+ p[i++] = 0x00000000; // process request
171
+
172
+ p[i++] = 0x3000d; // (the tag id)
173
+ p[i++] = 4; // (size of the buffer)
174
+ p[i++] = 4; // (size of the data)
175
+ p[i++] = handle;
176
+
177
+ p[i++] = 0x00000000; // end tag
178
+ p[0] = i*sizeof *p; // actual size
179
+
180
+ if (mbox_property(file_desc, p) < 0)
181
+ return ~0;
182
+ else
183
+ return p[5];
184
+ }
185
+
186
+ unsigned mem_unlock(int file_desc, unsigned handle)
187
+ {
188
+ int i=0;
189
+ unsigned p[32];
190
+ p[i++] = 0; // size
191
+ p[i++] = 0x00000000; // process request
192
+
193
+ p[i++] = 0x3000e; // (the tag id)
194
+ p[i++] = 4; // (size of the buffer)
195
+ p[i++] = 4; // (size of the data)
196
+ p[i++] = handle;
197
+
198
+ p[i++] = 0x00000000; // end tag
199
+ p[0] = i*sizeof *p; // actual size
200
+
201
+ mbox_property(file_desc, p);
202
+ return p[5];
203
+ }
204
+
205
+ unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5)
206
+ {
207
+ int i=0;
208
+ unsigned p[32];
209
+ p[i++] = 0; // size
210
+ p[i++] = 0x00000000; // process request
211
+
212
+ p[i++] = 0x30010; // (the tag id)
213
+ p[i++] = 28; // (size of the buffer)
214
+ p[i++] = 28; // (size of the data)
215
+ p[i++] = code;
216
+ p[i++] = r0;
217
+ p[i++] = r1;
218
+ p[i++] = r2;
219
+ p[i++] = r3;
220
+ p[i++] = r4;
221
+ p[i++] = r5;
222
+
223
+ p[i++] = 0x00000000; // end tag
224
+ p[0] = i*sizeof *p; // actual size
225
+
226
+ mbox_property(file_desc, p);
227
+ return p[5];
228
+ }
229
+
230
+ unsigned qpu_enable(int file_desc, unsigned enable)
231
+ {
232
+ int i=0;
233
+ unsigned p[32];
234
+
235
+ p[i++] = 0; // size
236
+ p[i++] = 0x00000000; // process request
237
+
238
+ p[i++] = 0x30012; // (the tag id)
239
+ p[i++] = 4; // (size of the buffer)
240
+ p[i++] = 4; // (size of the data)
241
+ p[i++] = enable;
242
+
243
+ p[i++] = 0x00000000; // end tag
244
+ p[0] = i*sizeof *p; // actual size
245
+
246
+ mbox_property(file_desc, p);
247
+ return p[5];
248
+ }
249
+
250
+ unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout) {
251
+ int i=0;
252
+ unsigned p[32];
253
+
254
+ p[i++] = 0; // size
255
+ p[i++] = 0x00000000; // process request
256
+ p[i++] = 0x30011; // (the tag id)
257
+ p[i++] = 16; // (size of the buffer)
258
+ p[i++] = 16; // (size of the data)
259
+ p[i++] = num_qpus;
260
+ p[i++] = control;
261
+ p[i++] = noflush;
262
+ p[i++] = timeout; // ms
263
+
264
+ p[i++] = 0x00000000; // end tag
265
+ p[0] = i*sizeof *p; // actual size
266
+
267
+ mbox_property(file_desc, p);
268
+ return p[5];
269
+ }
270
+
271
+ // mbox_open errors go here
272
+ int mbox_errno = MBOX_ERRNO_OK;
273
+
274
+ int mbox_open(void) {
275
+ int file_desc;
276
+ char *filename = NULL;
277
+
278
+ mbox_errno = MBOX_ERRNO_OK;
279
+
280
+ // open a char device file used for communicating with kernel mbox driver
281
+ filename = tempnam("/tmp", "mbox");
282
+ if (filename == NULL) {
283
+ mbox_errno = MBOX_ERRNO_CANT_TEMPNAM;
284
+ goto err;
285
+ }
286
+ unlink(filename);
287
+ if (mknod(filename, S_IFCHR|0600, makedev(100, 0)) < 0) {
288
+ // printf("Failed to create mailbox device %s: %m\n", filename);
289
+ mbox_errno = MBOX_ERRNO_CANT_MKNOD;
290
+ goto err;
291
+ }
292
+ file_desc = open(filename, 0);
293
+ if (file_desc < 0) {
294
+ // printf("Can't open device file %s: %m\n", filename);
295
+ mbox_errno = MBOX_ERRNO_CANT_OPEN;
296
+ goto err;
297
+ }
298
+ unlink(filename);
299
+
300
+ return file_desc;
301
+ err:
302
+ if (filename != NULL) {
303
+ unlink(filename);
304
+ free(filename);
305
+ }
306
+ return -1;
307
+ }
308
+
309
+ void mbox_close(int file_desc) {
310
+ close(file_desc);
311
+ }
@@ -0,0 +1,53 @@
1
+ /*
2
+ Copyright (c) 2012, Broadcom Europe Ltd.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ * Neither the name of the copyright holder nor the
13
+ names of its contributors may be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include <linux/ioctl.h>
29
+
30
+ #define MAJOR_NUM 100
31
+ #define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
32
+
33
+ #define MBOX_ERRNO_OK 0
34
+ #define MBOX_ERRNO_CANT_TEMPNAM 1
35
+ #define MBOX_ERRNO_CANT_MKNOD 2
36
+ #define MBOX_ERRNO_CANT_OPEN 3
37
+ // mbox_open errors go here
38
+ extern int mbox_errno;
39
+
40
+ int mbox_open(void);
41
+ void mbox_close(int file_desc);
42
+
43
+ unsigned get_version(int file_desc);
44
+ unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags);
45
+ unsigned mem_free(int file_desc, unsigned handle);
46
+ unsigned mem_lock(int file_desc, unsigned handle);
47
+ unsigned mem_unlock(int file_desc, unsigned handle);
48
+ void *mapmem(unsigned base, unsigned size);
49
+ void *unmapmem(void *addr, unsigned size);
50
+
51
+ unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5);
52
+ unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout);
53
+ unsigned qpu_enable(int file_desc, unsigned enable);
data/ext/ws2812/pwm.c ADDED
@@ -0,0 +1,112 @@
1
+ /*
2
+ * pwm.c
3
+ *
4
+ * Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
5
+ *
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
9
+ * provided that the following conditions are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
12
+ * conditions and the following disclaimer.
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
14
+ * of conditions and the following disclaimer in the documentation and/or other materials
15
+ * provided with the distribution.
16
+ * 3. Neither the name of the owner nor the names of its contributors may be used to endorse
17
+ * or promote products derived from this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ */
29
+
30
+
31
+ #include <stdint.h>
32
+
33
+ #include "ws2811.h"
34
+
35
+ #include "pwm.h"
36
+
37
+
38
+ // Mapping of Pin to alternate function for PWM channel 0
39
+ const pwm_pin_table_t pwm_pin_chan0[] =
40
+ {
41
+ {
42
+ .pinnum = 12,
43
+ .altnum = 0,
44
+ },
45
+ {
46
+ .pinnum = 18,
47
+ .altnum = 5,
48
+ },
49
+ {
50
+ .pinnum = 40,
51
+ .altnum = 0,
52
+ },
53
+ {
54
+ .pinnum = 52,
55
+ .altnum = 1,
56
+ },
57
+ };
58
+
59
+ // Mapping of Pin to alternate function for PWM channel 1
60
+ const pwm_pin_table_t pwm_pin_chan1[] =
61
+ {
62
+ {
63
+ .pinnum = 13,
64
+ .altnum = 0,
65
+ },
66
+ {
67
+ .pinnum = 19,
68
+ .altnum = 5,
69
+ },
70
+ {
71
+ .pinnum = 41,
72
+ .altnum = 0,
73
+ },
74
+ {
75
+ .pinnum = 45,
76
+ .altnum = 0,
77
+ },
78
+ {
79
+ .pinnum = 53,
80
+ .altnum = 1,
81
+ },
82
+ };
83
+
84
+ const pwm_pin_tables_t pwm_pin_tables[RPI_PWM_CHANNELS] =
85
+ {
86
+ {
87
+ .pins = pwm_pin_chan0,
88
+ .count = sizeof(pwm_pin_chan0) / sizeof(pwm_pin_chan0[0]),
89
+ },
90
+ {
91
+ .pins = pwm_pin_chan1,
92
+ .count = sizeof(pwm_pin_chan1) / sizeof(pwm_pin_chan1[0]),
93
+ },
94
+ };
95
+
96
+
97
+ int pwm_pin_alt(int chan, int pinnum)
98
+ {
99
+ const pwm_pin_tables_t *pintable = &pwm_pin_tables[chan];
100
+ int i;
101
+
102
+ for (i = 0; i < pintable->count; i++)
103
+ {
104
+ if (pintable->pins[i].pinnum == pinnum)
105
+ {
106
+ return pintable->pins[i].altnum;
107
+ }
108
+ }
109
+
110
+ return -1;
111
+ }
112
+