TLIGHT_PRODUCTS / WS281X
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WS281XU.cpp Source File

WS281XU.cpp

00001 /* WS281XU.cpp (for LPC82X/STM32F0x/STM32F746xx)
00002  * mbed Microcontroller Library
00003  * Copyright (c) 2016 muetch, t.kuroki
00004  * Allrights reserved.
00005  *
00006  * Rev 0.97 2016-09-07
00007  * Rev 0.98 2016-09-08
00008  */
00009 
00010 #include "WS281XU.h"
00011 #if defined(TARGET_STM)
00012 #include "pinmap.h"
00013 #endif
00014 
00015 // TARGET_STM32F7
00016 // TARGET_DISCO_F746NG
00017 // TARGET_NUCLEO_F746ZG
00018 // TARGET_NUCLEO_F446RE
00019 // TARGET_STM32F0
00020 // TARGET_NUCLEO_F030R8
00021 // TARGET_NUCLEO_F070RB
00022 // TARGET_NUCLEO_F072RB
00023 // TARGET_NUCLEO_F091RC
00024 // TARGET_LPC82X
00025 // TARGET_LPC824
00026 
00027 //----------------------------------------------------------------------------
00028 /* USART は下位ビットから送信
00029  * 800k*3 = 2.4Mbps, N, 7, 1
00030  * start_bit + 7bit_data + stop_bit = 9bit
00031  * 出力BITは反転させる
00032  * WS2811(RGB)/WS2812'GRB)は最上位ビットから送信
00033  */
00034 
00035 #define _0  0b110
00036 #define _1  0b100
00037 
00038 #define _B(b2,b1,b0)    ((((b2)|((b1)<<3)|((b0)<<6)) >> 1) & 0x7f)
00039 
00040 static const uint8_t wstab[8] =
00041 {
00042     _B(_0, _0, _0),
00043     _B(_0, _0, _1),
00044     _B(_0, _1, _0),
00045     _B(_0, _1, _1),
00046     _B(_1, _0, _0),
00047     _B(_1, _0, _1),
00048     _B(_1, _1, _0),
00049     _B(_1, _1, _1)
00050 };
00051 
00052 //----------------------------------------------------------------------------
00053 WS281XU::WS281XU(PinName txPin, PinMode pinMode, int maxPixels, RGBOrder order)
00054     : RGBPixels(maxPixels), _serial(), _irq_enabled(false)
00055 {
00056     pin_init(txPin, pinMode);
00057     rgbOrder(order);
00058     show(CL_BLACK);
00059 }
00060 
00061 WS281XU::WS281XU(PinName txPin, PinMode pinMode,
00062         RGBColor *buffer, int maxPixels, RGBOrder order)
00063     : RGBPixels(buffer, maxPixels), _serial(), _irq_enabled(false)
00064 {
00065     pin_init(txPin, pinMode);
00066     rgbOrder(order);
00067     show(CL_BLACK);
00068 }
00069 
00070 WS281XU::~WS281XU()
00071 {
00072     serial_free(&_serial);
00073 }
00074 
00075 void WS281XU::pin_init(PinName txPin, PinMode pinMode)
00076 {
00077     _txPin = txPin;
00078     serial_init(&_serial, _txPin, NC);
00079     serial_baud(&_serial, 800000*3);
00080     serial_format(&_serial, 7, ParityNone, 1);
00081 #if defined(TARGET_STM)
00082     pin_mode_ex(txPin, pinMode);
00083 #endif
00084 }
00085 
00086 #if defined(TARGET_STM)
00087 /**
00088  * Configure pin pull-up/pull-down/OpenDrain
00089  * typedef enum {
00090  *     PullNone  = 0,
00091  *     PullUp    = 1,
00092  *     PullDown  = 2,
00093  *     OpenDrain = 3,
00094  *     PullDefault = PullNone
00095  * } PinMode;
00096  */
00097 void WS281XU::pin_mode_ex(PinName pin, PinMode mode)
00098 {
00099     int port_index = STM_PORT(pin);
00100     int pin_index = STM_PIN(pin);
00101     int offset = pin_index << 1;
00102     GPIO_TypeDef * port_reg = ((GPIO_TypeDef *) (GPIOA_BASE + (port_index << 10)));
00103 
00104     // Configure pull-up/pull-down resistors
00105     uint32_t pupd = (uint32_t)mode & 3;
00106     if (pupd > 2)
00107         pupd = 0; // Open-drain = No pull-up/No pull-down
00108 
00109     if (mode == OpenDrain)
00110     {
00111         port_reg->PUPDR &= ~(0x3 << offset);    // Open-drain = No pull-up/No pull-down
00112         port_reg->OTYPER |= 1 << pin_index;
00113     }
00114     else
00115     {
00116         port_reg->OTYPER &= ~(1 << pin_index);
00117 //      pin_mode(pin, mode);
00118         port_reg->PUPDR &= ~(0x3 << offset);
00119         port_reg->PUPDR |= (mode & 0x03) << offset;
00120     }
00121 }
00122 #endif
00123 
00124 WS281XU::RGBOrder WS281XU::rgbOrder(RGBOrder order)
00125 {
00126     switch(_rgb_order = order)
00127     {
00128         case RGB: _1st = 0; _2nd = 1; _3rd = 2; break;  // WS2811
00129         case RBG: _1st = 0; _2nd = 2; _3rd = 1; break;
00130         case GRB: _1st = 1; _2nd = 0; _3rd = 2; break;  // WS2812
00131         case GBR: _1st = 2; _2nd = 0; _3rd = 1; break;
00132         case BRG: _1st = 1; _2nd = 2; _3rd = 0; break;
00133         case BGR: _1st = 2; _2nd = 1; _3rd = 0; break;
00134         default:
00135             _1st = 0; _2nd = 1; _3rd = 2;
00136             _rgb_order = GRB;    // WS2812
00137             break;
00138     }
00139     return _rgb_order;
00140 }
00141 
00142 void WS281XU::show()
00143 {
00144     if (!_pixels)
00145         return;
00146 
00147     uint8_t *pix = (uint8_t *)_pixels;
00148     uint8_t *end = pix + (_num_pixels * sizeof(_pixels[0]));
00149 
00150     if (!_irq_enabled)
00151         __disable_irq();   // Disable interrupts temporarily because we don't want our pulse timing to be messed up.
00152 
00153     uint32_t value;
00154     do
00155     {
00156         value  = pix[_1st];
00157         putByte(wstab[(value >> 5) & 7]);
00158         putByte(wstab[(value >> 2) & 7]);
00159 
00160         value = (value << 8) | pix[_2nd];
00161         putByte(wstab[(value >> 7) & 7]);
00162         putByte(wstab[(value >> 4) & 7]);
00163         putByte(wstab[(value >> 1) & 7]);
00164 
00165         value = (value << 8) | pix[_3rd];
00166         putByte(wstab[(value >> 6) & 7]);
00167         putByte(wstab[(value >> 3) & 7]);
00168         putByte(wstab[value & 7]);
00169 
00170         pix += sizeof(_pixels[0]);
00171     } while (pix < end);
00172 
00173     if (!_irq_enabled)
00174         __enable_irq();   // Re-enable interrupts now that we are done.
00175 
00176 //@-    wait_us(50);
00177 }
00178 
00179 // 指定色でバッファを埋めた後表示
00180 void WS281XU::show(const RGBColor color)
00181 {
00182     fill(color);
00183     show();
00184 }
00185 
00186 //----------------------------------------------------------------------------