forked from Aircoookie/WLED
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into merge-master
- Loading branch information
Showing
32 changed files
with
2,111 additions
and
416 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
/* | ||
MY92XX LED Driver for Arduino | ||
Based on the C driver by MaiKe Labs | ||
Copyright (c) 2016 - 2026 MaiKe Labs | ||
Copyright (C) 2017 - 2018 Xose Pérez for the Arduino compatible library | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef _my92xx_h | ||
#define _my92xx_h | ||
|
||
#include <Arduino.h> | ||
|
||
#ifdef DEBUG_MY92XX | ||
#if ARDUINO_ARCH_ESP8266 | ||
#define DEBUG_MSG_MY92XX(...) DEBUG_MY92XX.printf( __VA_ARGS__ ) | ||
#elif ARDUINO_ARCH_AVR | ||
#define DEBUG_MSG_MY92XX(...) { char buffer[80]; snprintf(buffer, sizeof(buffer), __VA_ARGS__ ); DEBUG_MY92XX.print(buffer); } | ||
#endif | ||
#else | ||
#define DEBUG_MSG_MY92XX(...) | ||
#endif | ||
|
||
typedef enum my92xx_model_t { | ||
MY92XX_MODEL_MY9291 = 0X00, | ||
MY92XX_MODEL_MY9231 = 0X01, | ||
} my92xx_model_t; | ||
|
||
typedef enum my92xx_cmd_one_shot_t { | ||
MY92XX_CMD_ONE_SHOT_DISABLE = 0X00, | ||
MY92XX_CMD_ONE_SHOT_ENFORCE = 0X01, | ||
} my92xx_cmd_one_shot_t; | ||
|
||
typedef enum my92xx_cmd_reaction_t { | ||
MY92XX_CMD_REACTION_FAST = 0X00, | ||
MY92XX_CMD_REACTION_SLOW = 0X01, | ||
} my92xx_cmd_reaction_t; | ||
|
||
typedef enum my92xx_cmd_bit_width_t { | ||
MY92XX_CMD_BIT_WIDTH_16 = 0X00, | ||
MY92XX_CMD_BIT_WIDTH_14 = 0X01, | ||
MY92XX_CMD_BIT_WIDTH_12 = 0X02, | ||
MY92XX_CMD_BIT_WIDTH_8 = 0X03, | ||
} my92xx_cmd_bit_width_t; | ||
|
||
typedef enum my92xx_cmd_frequency_t { | ||
MY92XX_CMD_FREQUENCY_DIVIDE_1 = 0X00, | ||
MY92XX_CMD_FREQUENCY_DIVIDE_4 = 0X01, | ||
MY92XX_CMD_FREQUENCY_DIVIDE_16 = 0X02, | ||
MY92XX_CMD_FREQUENCY_DIVIDE_64 = 0X03, | ||
} my92xx_cmd_frequency_t; | ||
|
||
typedef enum my92xx_cmd_scatter_t { | ||
MY92XX_CMD_SCATTER_APDM = 0X00, | ||
MY92XX_CMD_SCATTER_PWM = 0X01, | ||
} my92xx_cmd_scatter_t; | ||
|
||
typedef struct { | ||
my92xx_cmd_scatter_t scatter : 1; | ||
my92xx_cmd_frequency_t frequency : 2; | ||
my92xx_cmd_bit_width_t bit_width : 2; | ||
my92xx_cmd_reaction_t reaction : 1; | ||
my92xx_cmd_one_shot_t one_shot : 1; | ||
unsigned char resv : 1; | ||
} __attribute__((aligned(1), packed)) my92xx_cmd_t; | ||
|
||
#define MY92XX_COMMAND_DEFAULT { \ | ||
.scatter = MY92XX_CMD_SCATTER_APDM, \ | ||
.frequency = MY92XX_CMD_FREQUENCY_DIVIDE_1, \ | ||
.bit_width = MY92XX_CMD_BIT_WIDTH_8, \ | ||
.reaction = MY92XX_CMD_REACTION_FAST, \ | ||
.one_shot = MY92XX_CMD_ONE_SHOT_DISABLE, \ | ||
.resv = 0 \ | ||
} | ||
|
||
class my92xx { | ||
|
||
public: | ||
|
||
my92xx(my92xx_model_t model, unsigned char chips, unsigned char di, unsigned char dcki, my92xx_cmd_t command); | ||
unsigned char getChannels(); | ||
void setChannel(unsigned char channel, unsigned int value); | ||
unsigned int getChannel(unsigned char channel); | ||
void setState(bool state); | ||
bool getState(); | ||
void update(); | ||
|
||
private: | ||
|
||
void _di_pulse(unsigned int times); | ||
void _dcki_pulse(unsigned int times); | ||
void _set_cmd(my92xx_cmd_t command); | ||
void _send(); | ||
void _write(unsigned int data, unsigned char bit_length); | ||
|
||
my92xx_cmd_t _command; | ||
my92xx_model_t _model = MY92XX_MODEL_MY9291; | ||
unsigned char _chips = 1; | ||
unsigned char _channels; | ||
uint16_t* _value; | ||
bool _state = false; | ||
unsigned char _pin_di; | ||
unsigned char _pin_dcki; | ||
|
||
|
||
}; | ||
|
||
|
||
#if ARDUINO_ARCH_ESP8266 | ||
|
||
extern "C" { | ||
void os_delay_us(unsigned int); | ||
} | ||
|
||
#elif ARDUINO_ARCH_AVR | ||
|
||
#define os_delay_us delayMicroseconds | ||
|
||
#endif | ||
|
||
void my92xx::_di_pulse(unsigned int times) { | ||
for (unsigned int i = 0; i < times; i++) { | ||
digitalWrite(_pin_di, HIGH); | ||
digitalWrite(_pin_di, LOW); | ||
} | ||
} | ||
|
||
void my92xx::_dcki_pulse(unsigned int times) { | ||
for (unsigned int i = 0; i < times; i++) { | ||
digitalWrite(_pin_dcki, HIGH); | ||
digitalWrite(_pin_dcki, LOW); | ||
} | ||
} | ||
|
||
void my92xx::_write(unsigned int data, unsigned char bit_length) { | ||
|
||
unsigned int mask = (0x01 << (bit_length - 1)); | ||
|
||
for (unsigned int i = 0; i < bit_length / 2; i++) { | ||
digitalWrite(_pin_dcki, LOW); | ||
digitalWrite(_pin_di, (data & mask) ? HIGH : LOW); | ||
digitalWrite(_pin_dcki, HIGH); | ||
data = data << 1; | ||
digitalWrite(_pin_di, (data & mask) ? HIGH : LOW); | ||
digitalWrite(_pin_dcki, LOW); | ||
digitalWrite(_pin_di, LOW); | ||
data = data << 1; | ||
} | ||
|
||
} | ||
|
||
void my92xx::_set_cmd(my92xx_cmd_t command) { | ||
|
||
// ets_intr_lock(); | ||
|
||
// TStop > 12us. | ||
os_delay_us(12); | ||
|
||
// Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 | ||
// pulse's rising edge convert to command mode. | ||
_di_pulse(12); | ||
|
||
// Delay >12us, begin send CMD data | ||
os_delay_us(12); | ||
|
||
// Send CMD data | ||
unsigned char command_data = *(unsigned char*)(&command); | ||
for (unsigned char i = 0; i < _chips; i++) { | ||
_write(command_data, 8); | ||
} | ||
|
||
// TStart > 12us. Delay 12 us. | ||
os_delay_us(12); | ||
|
||
// Send 16 DI pulse,at 14 pulse's falling edge store CMD data, and | ||
// at 16 pulse's falling edge convert to duty mode. | ||
_di_pulse(16); | ||
|
||
// TStop > 12us. | ||
os_delay_us(12); | ||
|
||
// ets_intr_unlock(); | ||
|
||
} | ||
|
||
void my92xx::_send() { | ||
|
||
#ifdef DEBUG_MY92XX | ||
DEBUG_MSG_MY92XX("[MY92XX] Refresh: %s (", _state ? "ON" : "OFF"); | ||
for (unsigned char channel = 0; channel < _channels; channel++) { | ||
DEBUG_MSG_MY92XX(" %d", _value[channel]); | ||
} | ||
DEBUG_MSG_MY92XX(" )\n"); | ||
#endif | ||
|
||
unsigned char bit_length = 8; | ||
switch (_command.bit_width) { | ||
case MY92XX_CMD_BIT_WIDTH_16: | ||
bit_length = 16; | ||
break; | ||
case MY92XX_CMD_BIT_WIDTH_14: | ||
bit_length = 14; | ||
break; | ||
case MY92XX_CMD_BIT_WIDTH_12: | ||
bit_length = 12; | ||
break; | ||
case MY92XX_CMD_BIT_WIDTH_8: | ||
bit_length = 8; | ||
break; | ||
default: | ||
bit_length = 8; | ||
break; | ||
} | ||
|
||
// ets_intr_lock(); | ||
|
||
// TStop > 12us. | ||
os_delay_us(12); | ||
|
||
// Send color data | ||
for (unsigned char channel = 0; channel < _channels; channel++) { | ||
_write(_state ? _value[channel] : 0, bit_length); | ||
} | ||
|
||
// TStart > 12us. Ready for send DI pulse. | ||
os_delay_us(12); | ||
|
||
// Send 8 DI pulse. After 8 pulse falling edge, store old data. | ||
_di_pulse(8); | ||
|
||
// TStop > 12us. | ||
os_delay_us(12); | ||
|
||
// ets_intr_unlock(); | ||
|
||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
|
||
unsigned char my92xx::getChannels() { | ||
return _channels; | ||
} | ||
|
||
void my92xx::setChannel(unsigned char channel, unsigned int value) { | ||
if (channel < _channels) { | ||
_value[channel] = value; | ||
} | ||
} | ||
|
||
unsigned int my92xx::getChannel(unsigned char channel) { | ||
if (channel < _channels) { | ||
return _value[channel]; | ||
} | ||
return 0; | ||
} | ||
|
||
bool my92xx::getState() { | ||
return _state; | ||
} | ||
|
||
void my92xx::setState(bool state) { | ||
_state = state; | ||
} | ||
|
||
void my92xx::update() { | ||
_send(); | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
|
||
my92xx::my92xx(my92xx_model_t model, unsigned char chips, unsigned char di, unsigned char dcki, my92xx_cmd_t command) : _command(command) { | ||
|
||
_model = model; | ||
_chips = chips; | ||
_pin_di = di; | ||
_pin_dcki = dcki; | ||
|
||
// Init channels | ||
if (_model == MY92XX_MODEL_MY9291) { | ||
_channels = 4 * _chips; | ||
} | ||
else if (_model == MY92XX_MODEL_MY9231) { | ||
_channels = 3 * _chips; | ||
} | ||
_value = new uint16_t[_channels]; | ||
for (unsigned char i = 0; i < _channels; i++) { | ||
_value[i] = 0; | ||
} | ||
|
||
// Init GPIO | ||
pinMode(_pin_di, OUTPUT); | ||
pinMode(_pin_dcki, OUTPUT); | ||
digitalWrite(_pin_di, LOW); | ||
digitalWrite(_pin_dcki, LOW); | ||
|
||
// Clear all duty register | ||
_dcki_pulse(32 * _chips); | ||
|
||
// Send init command | ||
_set_cmd(command); | ||
|
||
DEBUG_MSG_MY92XX("[MY92XX] Initialized\n"); | ||
|
||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
|
||
#include "wled.h" | ||
#include "MY92xx.h" | ||
|
||
#define MY92XX_MODEL MY92XX_MODEL_MY9291 | ||
#define MY92XX_CHIPS 1 | ||
#define MY92XX_DI_PIN 13 | ||
#define MY92XX_DCKI_PIN 15 | ||
|
||
#define MY92XX_RED 0 | ||
#define MY92XX_GREEN 1 | ||
#define MY92XX_BLUE 2 | ||
#define MY92XX_WHITE 3 | ||
|
||
class MY9291Usermod : public Usermod { | ||
private: | ||
my92xx _my92xx = my92xx(MY92XX_MODEL, MY92XX_CHIPS, MY92XX_DI_PIN, MY92XX_DCKI_PIN, MY92XX_COMMAND_DEFAULT); | ||
|
||
public: | ||
|
||
void setup() { | ||
_my92xx.setState(true); | ||
} | ||
|
||
void connected() { | ||
} | ||
|
||
void loop() { | ||
uint32_t c = strip.getPixelColor(0); | ||
int w = ((c >> 24) & 0xff) * bri / 255.0; | ||
int r = ((c >> 16) & 0xff) * bri / 255.0; | ||
int g = ((c >> 8) & 0xff) * bri / 255.0; | ||
int b = (c & 0xff) * bri / 255.0; | ||
_my92xx.setChannel(MY92XX_RED, r); | ||
_my92xx.setChannel(MY92XX_GREEN, g); | ||
_my92xx.setChannel(MY92XX_BLUE, b); | ||
_my92xx.setChannel(MY92XX_WHITE, w); | ||
_my92xx.update(); | ||
} | ||
|
||
uint16_t getId() { | ||
return USERMOD_ID_MY9291; | ||
} | ||
}; |
Oops, something went wrong.