Skip to content

Commit c55be0c

Browse files
dimonomidcesantabot
authored andcommitted
Add C API to NeoPixel, example app
And refactor JS implementation on top of C. CL: Refactor neopixel to a separate lib and add C API, add a C example app (example-neopixel-c) PUBLISHED_FROM=bb01f7031303d0debd76ff89f7a45abc6945722d
1 parent c30eeae commit c55be0c

File tree

3 files changed

+165
-36
lines changed

3 files changed

+165
-36
lines changed

include/mgos_neopixel.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2014-2018 Cesanta Software Limited
3+
* All rights reserved
4+
*/
5+
6+
#ifndef CS_MOS_LIBS_NEOPIXEL_INCLUDE_MGOS_NEOPIXEL_H_
7+
#define CS_MOS_LIBS_NEOPIXEL_INCLUDE_MGOS_NEOPIXEL_H_
8+
9+
#include <stdbool.h>
10+
11+
#if defined(__cplusplus)
12+
extern "C" { // Make sure we have C-declarations in C++ programs
13+
#endif
14+
15+
/*
16+
* Pixel order: RGB, GRB, or BGR.
17+
*/
18+
enum mgos_neopixel_order {
19+
MGOS_NEOPIXEL_ORDER_RGB,
20+
MGOS_NEOPIXEL_ORDER_GRB,
21+
MGOS_NEOPIXEL_ORDER_BGR,
22+
};
23+
24+
/*
25+
* Opaque neopixel instance
26+
*/
27+
struct mgos_neopixel;
28+
29+
/*
30+
* Create and return a NeoPixel strip object. Example:
31+
* ```c
32+
* struct mgos_neopixel *mystrip = mgos_neopixel_create(
33+
* 5, 16, MGOS_NEOPIXEL_ORDER_GRB);
34+
* mgos_neopixel_set(mystrip, 0, 12, 34, 56);
35+
* mgos_neopixel_show(mystrip);
36+
*
37+
* mgos_neopixel_clear(mystrip);
38+
* mgos_neopixel_set(mystrip, 1, 12, 34, 56);
39+
* mgos_neopixel_show(mystrip);
40+
* ```
41+
*/
42+
struct mgos_neopixel *mgos_neopixel_create(int pin, int num_pixels,
43+
enum mgos_neopixel_order order);
44+
45+
/*
46+
* Set i-th pixel's RGB value. Each color (`r`, `g`, `b`) should be an integer
47+
* from 0 to 255; they are ints and not `uint8_t`s just for the FFI.
48+
*
49+
* Note that this only affects in-memory value of the pixel; you'll need to
50+
* call `mgos_neopixel_show()` to apply changes.
51+
*/
52+
void mgos_neopixel_set(struct mgos_neopixel *np, int i, int r, int g, int b);
53+
54+
/*
55+
* Clear in-memory values of the pixels.
56+
*/
57+
void mgos_neopixel_clear(struct mgos_neopixel *np);
58+
59+
/*
60+
* Output values of the pixels.
61+
*/
62+
void mgos_neopixel_show(struct mgos_neopixel *np);
63+
64+
/*
65+
* Free neopixel instance.
66+
*/
67+
void mgos_neopixel_free(struct mgos_neopixel *np);
68+
69+
#if defined(__cplusplus)
70+
}
71+
#endif
72+
73+
#endif /* CS_MOS_LIBS_NEOPIXEL_INCLUDE_MGOS_NEOPIXEL_H_ */

mjs_fs/api_neopixel.js

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,58 +20,36 @@ let NeoPixel = {
2020
// strip.show();
2121
// ```
2222
create: function(pin, numPixels, order) {
23-
GPIO.set_mode(pin, GPIO.MODE_OUTPUT);
24-
GPIO.write(pin, 0); // Keep in reset.
25-
let s = Object.create({
26-
pin: pin,
27-
len: numPixels * 3,
28-
// Note: memory allocated here is currently not released.
29-
// This should be ok for now, we don't expect strips to be re-created.
30-
data: Sys.malloc(numPixels * 3),
31-
order: order,
32-
setPixel: NeoPixel.set,
23+
return Object.create({
24+
_i: NeoPixel._c(pin, numPixels, order),
25+
26+
setPixel: NeoPixel.setPixel,
3327
clear: NeoPixel.clear,
3428
show: NeoPixel.show,
3529
});
36-
s.clear();
37-
return s;
3830
},
3931

4032
// ## **`strip.setPixel(i, r, g, b)`**
4133
// Set i-th's pixel's RGB value.
4234
// Note that this only affects in-memory value of the pixel.
43-
set: function(i, r, g, b) {
44-
let v0, v1, v2;
45-
if (this.order === NeoPixel.RGB) {
46-
v0 = r; v1 = g; v2 = b;
47-
} else if (this.order === NeoPixel.GRB) {
48-
v0 = g; v1 = r; v2 = b;
49-
} else if (this.order === NeoPixel.BGR) {
50-
v0 = b; v1 = g; v2 = r;
51-
} else {
52-
return;
53-
}
54-
this.data[i * 3] = v0;
55-
this.data[i * 3 + 1] = v1;
56-
this.data[i * 3 + 2] = v2;
35+
setPixel: function(i, r, g, b) {
36+
NeoPixel._set(this._i, i, r, g, b);
5737
},
5838

5939
// ## **`strip.clear()`**
6040
// Clear in-memory values of the pixels.
6141
clear: function() {
62-
for (let i = 0; i < this.len; i++) {
63-
this.data[i] = 0;
64-
}
42+
NeoPixel._clear(this._i);
6543
},
6644

6745
// ## **`strip.show()`**
6846
// Output values of the pixels.
6947
show: function() {
70-
GPIO.write(this.pin, 0);
71-
Sys.usleep(60);
72-
BitBang.write(this.pin, BitBang.DELAY_100NSEC, 3, 8, 8, 6, this.data, this.len);
73-
GPIO.write(this.pin, 0);
74-
Sys.usleep(60);
75-
GPIO.write(this.pin, 1);
48+
NeoPixel._show(this._i);
7649
},
50+
51+
_c: ffi('void *mgos_neopixel_create(int, int, int)'),
52+
_set: ffi('void mgos_neopixel_set(void *, int, int, int, int)'),
53+
_clear: ffi('void mgos_neopixel_clear(void *)'),
54+
_show: ffi('void mgos_neopixel_show(void *)'),
7755
};

src/mgos_neopixel.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,85 @@
33
* All rights reserved
44
*/
55

6-
#include <stdbool.h>
6+
#include <stdlib.h>
7+
#include <stdint.h>
8+
9+
#include "mgos_neopixel.h"
10+
11+
#include "common/cs_dbg.h"
12+
#include "mgos_bitbang.h"
13+
#include "mgos_gpio.h"
14+
#include "mgos_system.h"
15+
16+
#define NUM_CHANNELS 3 /* r, g, b */
17+
18+
struct mgos_neopixel {
19+
int pin;
20+
int num_pixels;
21+
enum mgos_neopixel_order order;
22+
uint8_t *data;
23+
};
24+
25+
struct mgos_neopixel *mgos_neopixel_create(int pin, int num_pixels,
26+
enum mgos_neopixel_order order) {
27+
mgos_gpio_set_mode(pin, MGOS_GPIO_MODE_OUTPUT);
28+
/* Keep in reset */
29+
mgos_gpio_write(pin, 0);
30+
31+
struct mgos_neopixel *np = calloc(1, sizeof(*np));
32+
np->pin = pin;
33+
np->num_pixels = num_pixels;
34+
np->order = order;
35+
np->data = malloc(num_pixels * NUM_CHANNELS);
36+
mgos_neopixel_clear(np);
37+
return np;
38+
}
39+
40+
void mgos_neopixel_set(struct mgos_neopixel *np, int i, int r, int g, int b) {
41+
uint8_t *p = np->data + i * NUM_CHANNELS;
42+
switch (np->order) {
43+
case MGOS_NEOPIXEL_ORDER_RGB:
44+
p[0] = r;
45+
p[1] = g;
46+
p[2] = b;
47+
break;
48+
49+
case MGOS_NEOPIXEL_ORDER_GRB:
50+
p[0] = g;
51+
p[1] = r;
52+
p[2] = b;
53+
break;
54+
55+
case MGOS_NEOPIXEL_ORDER_BGR:
56+
p[0] = b;
57+
p[1] = g;
58+
p[2] = r;
59+
break;
60+
61+
default:
62+
LOG(LL_ERROR, ("Wrong order: %d", np->order));
63+
break;
64+
}
65+
}
66+
67+
void mgos_neopixel_clear(struct mgos_neopixel *np) {
68+
memset(np->data, 0, np->num_pixels * NUM_CHANNELS);
69+
}
70+
71+
void mgos_neopixel_show(struct mgos_neopixel *np) {
72+
mgos_gpio_write(np->pin, 0);
73+
mgos_usleep(60);
74+
mgos_bitbang_write_bits(np->pin, MGOS_DELAY_100NSEC, 3, 8, 8, 6, np->data,
75+
np->num_pixels * NUM_CHANNELS);
76+
mgos_gpio_write(np->pin, 0);
77+
mgos_usleep(60);
78+
mgos_gpio_write(np->pin, 1);
79+
}
80+
81+
void mgos_neopixel_free(struct mgos_neopixel *np) {
82+
free(np->data);
83+
free(np);
84+
}
785

886
bool mgos_neopixel_init(void) {
987
return true;

0 commit comments

Comments
 (0)