Skip to content

Commit 8518072

Browse files
committed
Add support for led refresh rate limiting option
1 parent 2611359 commit 8518072

File tree

4 files changed

+99
-68
lines changed

4 files changed

+99
-68
lines changed

examples/_config.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,32 @@ import {
33
LedMatrix,
44
// LedMatrixUtils,
55
MatrixOptions,
6+
RuntimeFlag,
67
// PixelMapperType,
78
RuntimeOptions,
89
} from '../src';
910

1011
export const matrixOptions: MatrixOptions = {
1112
...LedMatrix.defaultMatrixOptions(),
12-
rows: 32,
13+
rows: 64,
1314
cols: 64,
1415
chainLength: 2,
1516
hardwareMapping: GpioMapping.Regular,
16-
parallel: 1,
17+
parallel: 2,
18+
// limitRefreshRateHz: 1,
19+
showRefreshRate: true,
1720
// pixelMapperConfig: LedMatrixUtils.encodeMappers(
1821
// { type: PixelMapperType.Chainlink }
1922
// ),
2023
// pixelMapperConfig: LedMatrixUtils.encodeMappers({ type: PixelMapperType.U }),
2124
};
2225

26+
console.log('matrix options: ', JSON.stringify(matrixOptions, null, 2));
27+
2328
export const runtimeOptions: RuntimeOptions = {
2429
...LedMatrix.defaultRuntimeOptions(),
2530
gpioSlowdown: 4,
31+
dropPrivileges: RuntimeFlag.Off,
2632
};
33+
34+
console.log('runtime options: ', JSON.stringify(runtimeOptions, null, 2));

nodemon.build.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"ext": "ts,json,cc,h,gyp",
3-
"exec": "npm run quick-build && npm run example -- examples/kitchen-sink.ts",
3+
"exec": "npm run quick-build && sudo npm run example -- examples/kitchen-sink.ts",
44
"restartable": true,
55
"events": {},
66
"watch": [

src/led-matrix.addon.cc

Lines changed: 54 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
#include "led-matrix.addon.h"
22

3-
#define BILLION 1000000000L;
4-
#define MILLION 1000000000L;
3+
#define BILLION 1000000000L;
4+
#define MILLION 1000000000L;
55

66
inline double get_now_ms() {
77
struct timespec t;
8-
if (clock_gettime(CLOCK_MONOTONIC_RAW, &t) < 0) {
9-
throw "Failed to get the current time.";
10-
}
8+
if (clock_gettime(CLOCK_MONOTONIC_RAW, &t) < 0) { throw "Failed to get the current time."; }
119

1210
return (t.tv_sec * 1000) + (t.tv_nsec / 1000000);
1311
}
@@ -71,7 +69,7 @@ LedMatrixAddon::LedMatrixAddon(const Napi::CallbackInfo& info)
7169
if (!info[1].IsObject()) {
7270
throw Napi::Error::New(env, "Constructor expects its first parameter to be an object of runtime options!");
7371
}
74-
auto matrixOpts = create_matrix_options(env, info[0].As<Napi::Object>());
72+
auto matrixOpts = create_matrix_options(env, info[0].As<Napi::Object>());
7573
auto runtimeOpts = create_runtime_options(env, info[1].As<Napi::Object>());
7674

7775
this->matrix_ = CreateMatrixFromOptions(matrixOpts, runtimeOpts);
@@ -98,20 +96,16 @@ Napi::Value LedMatrixAddon::sync(const Napi::CallbackInfo& info) {
9896
auto env = info.Env();
9997

10098
if (!after_sync_cb_.IsEmpty()) {
101-
auto now = get_now_ms();
102-
auto now_ms = now - t_start_;
103-
t_dsync_ms_ = now_ms - t_sync_ms_;
104-
t_sync_ms_ = now_ms;
105-
106-
auto resync = after_sync_cb_.Call(info.This(), {
107-
info.This(),
108-
Napi::Number::New(env, t_dsync_ms_),
109-
Napi::Number::New(env, t_sync_ms_)
110-
});
111-
112-
if (resync.ToBoolean() == true) {
113-
sync(info);
114-
}
99+
auto now = get_now_ms();
100+
auto now_ms = now - t_start_;
101+
t_dsync_ms_ = now_ms - t_sync_ms_;
102+
t_sync_ms_ = now_ms;
103+
104+
auto resync
105+
= after_sync_cb_
106+
.Call(info.This(), { info.This(), Napi::Number::New(env, t_dsync_ms_), Napi::Number::New(env, t_sync_ms_) });
107+
108+
if (resync.ToBoolean() == true) { sync(info); }
115109
}
116110

117111
return Napi::Number::New(env, 0);
@@ -133,35 +127,32 @@ Napi::Value LedMatrixAddon::map(const Napi::CallbackInfo& info) {
133127

134128
assert(cb.IsFunction());
135129

136-
auto env = info.Env();
137-
auto now = get_now_ms();
130+
auto env = info.Env();
131+
auto now = get_now_ms();
138132
auto now_ms = Napi::Number::New(env, now - t_start_);
139133

140-
Napi::Array coord_array = Napi::Array::New(env, 3);
141-
uint32_t zero = 0; // The compiler can't match the overloaded signature if given 0 explicitly
142-
uint32_t one = 1;
143-
uint32_t two = 2;
134+
Napi::Array coord_array = Napi::Array::New(env, 3);
135+
uint32_t zero = 0; // The compiler can't match the overloaded signature if given 0 explicitly
136+
uint32_t one = 1;
137+
uint32_t two = 2;
144138

145-
auto i = 0;
139+
auto i = 0;
146140

147-
for (int x = 0; x < this->matrix_->width(); x++) {
148-
coord_array.Set(zero, x);
141+
for (int x = 0; x < this->matrix_->width(); x++) {
142+
coord_array.Set(zero, x);
149143

150-
for (int y = 0; y < this->matrix_->height(); y++) {
151-
coord_array.Set(one, y);
152-
coord_array.Set(two, i++);
144+
for (int y = 0; y < this->matrix_->height(); y++) {
145+
coord_array.Set(one, y);
146+
coord_array.Set(two, i++);
153147

154-
auto color = cb.Call(info.This(), {
155-
coord_array,
156-
now_ms
157-
});
148+
auto color = cb.Call(info.This(), { coord_array, now_ms });
158149

159-
assert(color.IsNumber());
150+
assert(color.IsNumber());
160151

161-
const auto hex = color.As<Napi::Number>().Uint32Value();
162-
this->matrix_->SetPixel(x, y, 0xFF & (hex >> 16), 0xFF & (hex >> 8), 0xFF & hex);
163-
}
164-
}
152+
const auto hex = color.As<Napi::Number>().Uint32Value();
153+
this->matrix_->SetPixel(x, y, 0xFF & (hex >> 16), 0xFF & (hex >> 8), 0xFF & hex);
154+
}
155+
}
165156

166157
return info.This();
167158
}
@@ -179,10 +170,10 @@ Napi::Value LedMatrixAddon::brightness(const Napi::CallbackInfo& info) {
179170

180171
Napi::Value LedMatrixAddon::clear(const Napi::CallbackInfo& info) {
181172
if (info.Length() > 0) {
182-
const auto x0 = info[0].As<Napi::Number>().Uint32Value();
183-
const auto y0 = info[1].As<Napi::Number>().Uint32Value();
184-
const auto x1 = info[2].As<Napi::Number>().Uint32Value();
185-
const auto y1 = info[3].As<Napi::Number>().Uint32Value();
173+
const auto x0 = info[0].As<Napi::Number>().Uint32Value();
174+
const auto y0 = info[1].As<Napi::Number>().Uint32Value();
175+
const auto x1 = info[2].As<Napi::Number>().Uint32Value();
176+
const auto y1 = info[3].As<Napi::Number>().Uint32Value();
186177
const auto black = Color(0, 0, 0);
187178
for (auto y = y0; y <= y1; y++) { DrawLine(this->canvas_, x0, y, x1, y, black); }
188179
}
@@ -196,12 +187,12 @@ Napi::Value LedMatrixAddon::draw_buffer(const Napi::CallbackInfo& info) {
196187
const auto buffer = info[0].As<Napi::Buffer<uint8_t> >();
197188
const auto w = info[1].IsNumber() ? info[1].As<Napi::Number>().Uint32Value() : this->matrix_->width();
198189
const auto h = info[2].IsNumber() ? info[2].As<Napi::Number>().Uint32Value() : this->matrix_->height();
199-
const auto data = buffer.Data();
200-
const auto len = buffer.Length();
190+
const auto data = buffer.Data();
191+
const auto len = buffer.Length();
201192

202193
assert(len == w * h * 3);
203194

204-
Image* img = new Image();
195+
Image* img = new Image();
205196
Pixel* pixels = (Pixel*) malloc(sizeof(Pixel) * w * h);
206197
for (unsigned int i = 0; i < w * h; i++) {
207198
auto j = i * 3;
@@ -351,9 +342,9 @@ Napi::Value LedMatrixAddon::bg_color(const Napi::CallbackInfo& info) {
351342

352343
Napi::Value LedMatrixAddon::font(const Napi::CallbackInfo& info) {
353344
if (info.Length() > 0) {
354-
auto font = Napi::ObjectWrap<FontAddon>::Unwrap(info[0].As<Napi::Object>());
345+
auto font = Napi::ObjectWrap<FontAddon>::Unwrap(info[0].As<Napi::Object>());
355346
this->font_ = &(font->font);
356-
font_name_ = font->name(info).ToString();
347+
font_name_ = font->name(info).ToString();
357348
return info.This();
358349
}
359350
else {
@@ -362,18 +353,15 @@ Napi::Value LedMatrixAddon::font(const Napi::CallbackInfo& info) {
362353
}
363354

364355
Napi::Value LedMatrixAddon::get_available_pixel_mappers(const Napi::CallbackInfo& info) {
365-
auto env = info.Env();
366-
auto mappers = GetAvailablePixelMappers();
367-
Napi::Array mapper_name_array = Napi::Array::New(env, mappers.size());
356+
auto env = info.Env();
357+
auto mappers = GetAvailablePixelMappers();
358+
Napi::Array mapper_name_array = Napi::Array::New(env, mappers.size());
368359

369-
for (uint8_t i = 0; i < mappers.size(); i++) {
370-
mapper_name_array.Set(i, Napi::String::New(env, mappers.at(i)));
371-
}
360+
for (uint8_t i = 0; i < mappers.size(); i++) { mapper_name_array.Set(i, Napi::String::New(env, mappers.at(i))); }
372361

373-
return mapper_name_array;
362+
return mapper_name_array;
374363
}
375364

376-
377365
/**
378366
* Create an instance of Options from a JS object.
379367
*/
@@ -389,6 +377,7 @@ RGBMatrix::Options LedMatrixAddon::create_matrix_options(const Napi::Env& env, c
389377
options.inverse_colors = obj.Get("inverseColors").As<Napi::Boolean>();
390378
auto led_rgb_sequence = std::string(obj.Get("ledRgbSequence").As<Napi::String>());
391379
options.led_rgb_sequence = strcpy(new char[led_rgb_sequence.size()], led_rgb_sequence.c_str());
380+
options.limit_refresh_rate_hz = obj.Get("limitRefreshRateHz").As<Napi::Number>();
392381
auto pixel_mapper_config = std::string(obj.Get("pixelMapperConfig").As<Napi::String>());
393382
options.pixel_mapper_config = strcpy(new char[pixel_mapper_config.size()], pixel_mapper_config.c_str());
394383
options.multiplexing = obj.Get("multiplexing").As<Napi::Number>();
@@ -413,7 +402,7 @@ RGBMatrix::Options LedMatrixAddon::create_matrix_options(const Napi::Env& env, c
413402
RuntimeOptions LedMatrixAddon::create_runtime_options(const Napi::Env& env, const Napi::Object& obj) {
414403
RuntimeOptions options = RuntimeOptions();
415404

416-
options.gpio_slowdown = obj.Get("gpioSlowdown").As<Napi::Number>();
405+
options.gpio_slowdown = obj.Get("gpioSlowdown").As<Napi::Number>();
417406
options.daemon = obj.Get("daemon").As<Napi::Number>();
418407
options.drop_privileges = obj.Get("dropPrivileges").As<Napi::Number>();
419408
options.do_gpio_init = obj.Get("doGpioInit").As<Napi::Boolean>();
@@ -441,6 +430,7 @@ Napi::Object LedMatrixAddon::matrix_options_to_obj(const Napi::Env& env, const R
441430
obj.Set("hardwareMapping", Napi::String::New(env, hardware_mapping));
442431
obj.Set("inverseColors", Napi::Boolean::New(env, options.inverse_colors));
443432
obj.Set("ledRgbSequence", Napi::String::New(env, led_rgb_sequence));
433+
obj.Set("limitRefreshRateHz", Napi::Number::New(env, options.limit_refresh_rate_hz));
444434
obj.Set("multiplexing", Napi::Number::New(env, options.multiplexing));
445435
obj.Set("parallel", Napi::Number::New(env, options.parallel));
446436
obj.Set("pixelMapperConfig", Napi::String::New(env, pixel_mapper_config));
@@ -460,11 +450,10 @@ Napi::Object LedMatrixAddon::matrix_options_to_obj(const Napi::Env& env, const R
460450
*/
461451
Napi::Object LedMatrixAddon::runtime_options_to_obj(const Napi::Env& env, const RuntimeOptions& options) {
462452
auto obj = Napi::Object::New(env);
463-
464-
obj.Set("gpioSlowdown", Napi::Number::New(env, options.gpio_slowdown));
465453
obj.Set("daemon", Napi::Number::New(env, options.daemon));
466-
obj.Set("dropPrivileges", Napi::Number::New(env, options.drop_privileges));
467454
obj.Set("doGpioInit", Napi::Boolean::New(env, options.do_gpio_init));
455+
obj.Set("dropPrivileges", Napi::Number::New(env, options.drop_privileges));
456+
obj.Set("gpioSlowdown", Napi::Number::New(env, options.gpio_slowdown));
468457

469458
return obj;
470459
}
@@ -498,9 +487,9 @@ Color LedMatrixAddon::color_from_callback_info(const Napi::CallbackInfo& info) {
498487
}
499488
else if (info[0].IsObject()) {
500489
const auto obj = info[0].As<Napi::Object>();
501-
uint8_t r = obj.Get("r").As<Napi::Number>().Uint32Value();
502-
uint8_t g = obj.Get("g").As<Napi::Number>().Uint32Value();
503-
uint8_t b = obj.Get("b").As<Napi::Number>().Uint32Value();
490+
uint8_t r = obj.Get("r").As<Napi::Number>().Uint32Value();
491+
uint8_t g = obj.Get("g").As<Napi::Number>().Uint32Value();
492+
uint8_t b = obj.Get("b").As<Napi::Number>().Uint32Value();
504493
return Color(r, g, b);
505494
}
506495
else if (info[0].IsNumber()) {

src/types.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,39 @@ export enum RowAddressType {
7373
}
7474

7575
export enum GpioMapping {
76+
/**
77+
* The regular hardware mapping described in the wiring.md and used
78+
* by the adapter PCBs.
79+
*/
7680
Regular = 'regular',
81+
82+
/**
83+
* This is used if you have an Adafruit HAT in the default configuration
84+
*/
7785
AdafruitHat = 'adafruit-hat',
86+
87+
/**
88+
* An Adafruit HAT with the PWM modification
89+
*/
7890
AdafruitHatPwm = 'adafruit-hat-pwm',
91+
92+
/**
93+
* The regular pin-out, but for Raspberry Pi1. The very first Pi1 Rev1 uses
94+
* the same pin for GPIO-21 as later Pis use GPIO-27. Make it work for both.
95+
*/
7996
RegularPi1 = 'regular-pi1',
97+
98+
/**
99+
* Classic: Early forms of this library had this as default mapping, mostly
100+
* derived from the 26 GPIO-header version so that it also can work
101+
* on 40 Pin GPIO headers with more parallel chains.
102+
* Not used anymore.
103+
*/
80104
Classic = 'classic',
105+
106+
/**
107+
* Classic pin-out for Rev-A Raspberry Pi.
108+
*/
81109
ClassicPi1 = 'classic-pi1',
82110
}
83111

@@ -132,6 +160,12 @@ export interface MatrixOptions {
132160
*/
133161
ledRgbSequence: 'RGB' | 'BGR' | 'BRG' | 'RBG' | 'GRB' | 'GBR';
134162

163+
/**
164+
* Limit refresh rate of LED panel. This will help on a loaded system
165+
* to keep a constant refresh rate. <= 0 for no limit.
166+
*/
167+
limitRefreshRateHz: number;
168+
135169
/**
136170
* @default MuxType.Direct
137171
*/

0 commit comments

Comments
 (0)