mirror of
https://github.com/wled/WLED.git
synced 2025-04-24 06:47:18 +00:00
Better low brightness level PWM handling
Additional string optimisation
This commit is contained in:
parent
da6d64e581
commit
c0beb621e2
77
wled00/bus_manager.cpp
Executable file → Normal file
77
wled00/bus_manager.cpp
Executable file → Normal file
@ -376,14 +376,22 @@ BusPwm::BusPwm(BusConfig &bc)
|
||||
_frequency = bc.frequency ? bc.frequency : WLED_PWM_FREQ;
|
||||
|
||||
#ifdef ESP8266
|
||||
analogWriteRange(255); //same range as one RGB channel
|
||||
// duty cycle resolution (_depth) can be extracted from this formula: 1MHz > _frequency * 2^_depth
|
||||
if (_frequency > 1760) _depth = 8;
|
||||
else if (_frequency > 880) _depth = 9;
|
||||
else _depth = 10; // WLED_PWM_FREQ <= 880Hz
|
||||
analogWriteRange((1<<_depth)-1);
|
||||
analogWriteFreq(_frequency);
|
||||
#else
|
||||
_ledcStart = pinManager.allocateLedc(numPins);
|
||||
if (_ledcStart == 255) { //no more free LEDC channels
|
||||
deallocatePins(); return;
|
||||
}
|
||||
//_prevBri = _bri;
|
||||
// duty cycle resolution (_depth) can be extracted from this formula: 80MHz > _frequency * 2^_depth
|
||||
if (_frequency > 78124) _depth = 9;
|
||||
else if (_frequency > 39062) _depth = 10;
|
||||
else if (_frequency > 19531) _depth = 11;
|
||||
else _depth = 12; // WLED_PWM_FREQ <= 19531Hz
|
||||
#endif
|
||||
|
||||
for (unsigned i = 0; i < numPins; i++) {
|
||||
@ -395,14 +403,6 @@ BusPwm::BusPwm(BusConfig &bc)
|
||||
#ifdef ESP8266
|
||||
pinMode(_pins[i], OUTPUT);
|
||||
#else
|
||||
switch (_frequency) {
|
||||
case WLED_PWM_FREQ/3: _depth = 12; break; // 6510Hz
|
||||
case WLED_PWM_FREQ/2: _depth = 11; break; // 9676Hz
|
||||
default:
|
||||
case WLED_PWM_FREQ: _depth = 10; break; // 19531Hz
|
||||
case WLED_PWM_FREQ*4/3: _depth = 9; break; // 26041Hz
|
||||
case WLED_PWM_FREQ*2: _depth = 8; break; // 39062Hz
|
||||
}
|
||||
ledcSetup(_ledcStart + i, _frequency, _depth);
|
||||
ledcAttachPin(_pins[i], _ledcStart + i);
|
||||
#endif
|
||||
@ -411,13 +411,6 @@ BusPwm::BusPwm(BusConfig &bc)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void BusPwm::setBrightness(uint8_t bri) {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
//_prevBri = _bri;
|
||||
#endif
|
||||
Bus::setBrightness(bri);
|
||||
}
|
||||
|
||||
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
|
||||
@ -477,24 +470,52 @@ uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
||||
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
||||
}
|
||||
|
||||
#ifndef ESP8266
|
||||
static const uint16_t cieLUT[256] = {
|
||||
0, 2, 4, 5, 7, 9, 11, 13, 15, 16,
|
||||
18, 20, 22, 24, 26, 27, 29, 31, 33, 35,
|
||||
34, 36, 37, 39, 41, 43, 45, 47, 49, 52,
|
||||
54, 56, 59, 61, 64, 67, 69, 72, 75, 78,
|
||||
81, 84, 87, 90, 94, 97, 100, 104, 108, 111,
|
||||
115, 119, 123, 127, 131, 136, 140, 144, 149, 154,
|
||||
158, 163, 168, 173, 178, 183, 189, 194, 200, 205,
|
||||
211, 217, 223, 229, 235, 241, 247, 254, 261, 267,
|
||||
274, 281, 288, 295, 302, 310, 317, 325, 333, 341,
|
||||
349, 357, 365, 373, 382, 391, 399, 408, 417, 426,
|
||||
436, 445, 455, 464, 474, 484, 494, 505, 515, 526,
|
||||
536, 547, 558, 569, 580, 592, 603, 615, 627, 639,
|
||||
651, 663, 676, 689, 701, 714, 727, 741, 754, 768,
|
||||
781, 795, 809, 824, 838, 853, 867, 882, 897, 913,
|
||||
928, 943, 959, 975, 991, 1008, 1024, 1041, 1058, 1075,
|
||||
1092, 1109, 1127, 1144, 1162, 1180, 1199, 1217, 1236, 1255,
|
||||
1274, 1293, 1312, 1332, 1352, 1372, 1392, 1412, 1433, 1454,
|
||||
1475, 1496, 1517, 1539, 1561, 1583, 1605, 1628, 1650, 1673,
|
||||
1696, 1719, 1743, 1767, 1791, 1815, 1839, 1864, 1888, 1913,
|
||||
1939, 1964, 1990, 2016, 2042, 2068, 2095, 2121, 2148, 2176,
|
||||
2203, 2231, 2259, 2287, 2315, 2344, 2373, 2402, 2431, 2461,
|
||||
2491, 2521, 2551, 2581, 2612, 2643, 2675, 2706, 2738, 2770,
|
||||
2802, 2835, 2867, 2900, 2934, 2967, 3001, 3035, 3069, 3104,
|
||||
3138, 3174, 3209, 3244, 3280, 3316, 3353, 3389, 3426, 3463,
|
||||
3501, 3539, 3576, 3615, 3653, 3692, 3731, 3770, 3810, 3850,
|
||||
3890, 3930, 3971, 4012, 4053, 4095
|
||||
};
|
||||
#endif
|
||||
|
||||
void BusPwm::show() {
|
||||
if (!_valid) return;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
unsigned maxBri = (1<<_depth) - 1;
|
||||
#ifdef ESP8266
|
||||
unsigned pwmBri = (unsigned)(roundf(powf((float)_bri / 255.0f, 1.7f) * (float)maxBri + 0.5f)); // using gamma 1.7 to extrapolate PWM duty cycle
|
||||
#else
|
||||
unsigned pwmBri = cieLUT[_bri] >> (12 - _depth); // use CIE LUT
|
||||
#endif
|
||||
for (unsigned i = 0; i < numPins; i++) {
|
||||
unsigned scaled = (_data[i] * pwmBri) / 255;
|
||||
if (_reversed) scaled = maxBri - scaled;
|
||||
#ifdef ESP8266
|
||||
uint8_t scaled = (_data[i] * _bri) / 255;
|
||||
if (_reversed) scaled = 255 - scaled;
|
||||
analogWrite(_pins[i], scaled);
|
||||
#else
|
||||
unsigned scaled = ((_data[i] * _bri) << (_depth-8)) / 255;
|
||||
if (_reversed) scaled = (1<<_depth) - 1 - scaled;
|
||||
// TODO: implement ledcFade() if the brightness changed between calls
|
||||
// bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);
|
||||
// if (_prevBri != _bri) {
|
||||
// unsigned prevScaled = ((_data[i] * _prevBri) << (_depth-8)) / 255;
|
||||
// ledcFade(_ledcStart + i, prevScaled, scaled, FRAMETIME-1); // frametime is a macro expanding to strip.getFrameTime() which is unwanted here
|
||||
// _prevBri = _bri;
|
||||
// } else
|
||||
ledcWrite(_ledcStart + i, scaled);
|
||||
#endif
|
||||
}
|
||||
|
@ -255,7 +255,6 @@ class BusPwm : public Bus {
|
||||
BusPwm(BusConfig &bc);
|
||||
~BusPwm() { cleanup(); }
|
||||
|
||||
void setBrightness(uint8_t bri) override;
|
||||
void setPixelColor(uint16_t pix, uint32_t c) override;
|
||||
uint32_t getPixelColor(uint16_t pix) override; //does no index check
|
||||
uint8_t getPins(uint8_t* pinArray) override;
|
||||
@ -268,9 +267,8 @@ class BusPwm : public Bus {
|
||||
uint8_t _pwmdata[5];
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t _ledcStart;
|
||||
uint8_t _depth;
|
||||
//uint8_t _prevBri;
|
||||
#endif
|
||||
uint8_t _depth;
|
||||
uint16_t _frequency;
|
||||
|
||||
void deallocatePins();
|
||||
|
@ -180,7 +180,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
uint8_t ledType = elm["type"] | TYPE_WS2812_RGB;
|
||||
bool reversed = elm["rev"];
|
||||
bool refresh = elm["ref"] | false;
|
||||
uint16_t freqkHz = elm[F("freq")] | 0; // will be in kHz for DotStar and Hz for PWM (not yet implemented fully)
|
||||
uint16_t freqkHz = elm[F("freq")] | 0; // will be in kHz for DotStar and Hz for PWM
|
||||
uint8_t AWmode = elm[F("rgbwm")] | RGBW_MODE_MANUAL_ONLY;
|
||||
uint8_t maPerLed = elm[F("ledma")] | 55;
|
||||
uint16_t maMax = elm[F("maxpwr")] | (ablMilliampsMax * length) / total; // rough (incorrect?) per strip ABL calculation when no config exists
|
||||
@ -627,6 +627,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
return (doc["sv"] | true);
|
||||
}
|
||||
|
||||
|
||||
static const char s_cfg_json[] PROGMEM = "/cfg.json";
|
||||
|
||||
void deserializeConfigFromFS() {
|
||||
bool success = deserializeConfigSec();
|
||||
if (!success) { //if file does not exist, try reading from EEPROM
|
||||
@ -640,7 +643,7 @@ void deserializeConfigFromFS() {
|
||||
|
||||
DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
|
||||
|
||||
success = readObjectFromFile(PSTR("/cfg.json"), nullptr, pDoc);
|
||||
success = readObjectFromFile(s_cfg_json, nullptr, pDoc);
|
||||
if (!success) { // if file does not exist, optionally try reading from EEPROM and then save defaults to FS
|
||||
releaseJSONBufferLock();
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
@ -1065,7 +1068,7 @@ void serializeConfig() {
|
||||
JsonObject usermods_settings = root.createNestedObject("um");
|
||||
usermods.addToConfig(usermods_settings);
|
||||
|
||||
File f = WLED_FS.open(SET_F("/cfg.json"), "w");
|
||||
File f = WLED_FS.open(FPSTR(s_cfg_json), "w");
|
||||
if (f) serializeJson(root, f);
|
||||
f.close();
|
||||
releaseJSONBufferLock();
|
||||
@ -1073,13 +1076,16 @@ void serializeConfig() {
|
||||
doSerializeConfig = false;
|
||||
}
|
||||
|
||||
|
||||
static const char s_wsec_json[] PROGMEM = "/wsec.json";
|
||||
|
||||
//settings in /wsec.json, not accessible via webserver, for passwords and tokens
|
||||
bool deserializeConfigSec() {
|
||||
DEBUG_PRINTLN(F("Reading settings from /wsec.json..."));
|
||||
|
||||
if (!requestJSONBufferLock(3)) return false;
|
||||
|
||||
bool success = readObjectFromFile(PSTR("/wsec.json"), nullptr, pDoc);
|
||||
bool success = readObjectFromFile(s_wsec_json, nullptr, pDoc);
|
||||
if (!success) {
|
||||
releaseJSONBufferLock();
|
||||
return false;
|
||||
@ -1162,7 +1168,7 @@ void serializeConfigSec() {
|
||||
ota[F("lock-wifi")] = wifiLock;
|
||||
ota[F("aota")] = aOtaEnabled;
|
||||
|
||||
File f = WLED_FS.open(SET_F("/wsec.json"), "w");
|
||||
File f = WLED_FS.open(FPSTR(s_wsec_json), "w");
|
||||
if (f) serializeJson(root, f);
|
||||
f.close();
|
||||
releaseJSONBufferLock();
|
||||
|
@ -127,7 +127,7 @@ static bool remoteJson(int button)
|
||||
JsonObject fdo = pDoc->as<JsonObject>();
|
||||
if (fdo.isNull()) {
|
||||
// the received button does not exist
|
||||
//if (!WLED_FS.exists(SET_F("/remote.json"))) errorFlag = ERR_FS_RMLOAD; //warn if file itself doesn't exist
|
||||
//if (!WLED_FS.exists(F("/remote.json"))) errorFlag = ERR_FS_RMLOAD; //warn if file itself doesn't exist
|
||||
releaseJSONBufferLock();
|
||||
return parsed;
|
||||
}
|
||||
|
@ -167,12 +167,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
uint16_t freq = request->arg(sp).toInt();
|
||||
if (IS_PWM(type)) {
|
||||
switch (freq) {
|
||||
case 0 : freq = WLED_PWM_FREQ/3; break;
|
||||
case 1 : freq = WLED_PWM_FREQ/2; break;
|
||||
case 0 : freq = WLED_PWM_FREQ/2; break;
|
||||
case 1 : freq = WLED_PWM_FREQ*2/3; break;
|
||||
default:
|
||||
case 2 : freq = WLED_PWM_FREQ; break;
|
||||
case 3 : freq = WLED_PWM_FREQ*4/3; break;
|
||||
case 4 : freq = WLED_PWM_FREQ*2; break;
|
||||
case 3 : freq = WLED_PWM_FREQ*2; break;
|
||||
case 4 : freq = WLED_PWM_FREQ*4; break;
|
||||
}
|
||||
} else if (IS_DIGITAL(type) && IS_2PIN(type)) {
|
||||
switch (freq) {
|
||||
|
@ -402,12 +402,12 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
uint16_t speed = bus->getFrequency();
|
||||
if (IS_PWM(bus->getType())) {
|
||||
switch (speed) {
|
||||
case WLED_PWM_FREQ/3 : speed = 0; break;
|
||||
case WLED_PWM_FREQ/2 : speed = 1; break;
|
||||
case WLED_PWM_FREQ/2 : speed = 0; break;
|
||||
case WLED_PWM_FREQ*2/3 : speed = 1; break;
|
||||
default:
|
||||
case WLED_PWM_FREQ : speed = 2; break;
|
||||
case WLED_PWM_FREQ*4/3 : speed = 3; break;
|
||||
case WLED_PWM_FREQ*2 : speed = 4; break;
|
||||
case WLED_PWM_FREQ*2 : speed = 3; break;
|
||||
case WLED_PWM_FREQ*4 : speed = 4; break;
|
||||
}
|
||||
} else if (IS_DIGITAL(bus->getType()) && IS_2PIN(bus->getType())) {
|
||||
switch (speed) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user