Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
WS281X.cpp
00001 /* WS281X.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 "WS281X.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 WS281X::WS281X(PinName txPin, PinMode pinMode, int maxPixels, RGBOrder order) 00029 : RGBPixels(maxPixels), _gpio() 00030 { 00031 pin_init(txPin, pinMode); 00032 rgbOrder(order); 00033 show(CL_BLACK); 00034 } 00035 00036 WS281X::WS281X(PinName txPin, PinMode pinMode, 00037 RGBColor *buffer, int maxPixels, RGBOrder order) 00038 : RGBPixels(buffer, maxPixels), _gpio() 00039 { 00040 pin_init(txPin, pinMode); 00041 rgbOrder(order); 00042 show(CL_BLACK); 00043 } 00044 00045 void WS281X::pin_init(PinName txPin, PinMode pinMode) 00046 { 00047 _txPin = txPin; 00048 gpio_init_inout(&_gpio, txPin, PIN_OUTPUT, pinMode, 0); 00049 #if defined(TARGET_STM) 00050 pin_mode_ex(txPin, pinMode); 00051 #endif 00052 } 00053 00054 #if defined(TARGET_STM) 00055 /** 00056 * Configure pin pull-up/pull-down/OpenDrain 00057 * typedef enum { 00058 * PullNone = 0, 00059 * PullUp = 1, 00060 * PullDown = 2, 00061 * OpenDrain = 3, 00062 * PullDefault = PullNone 00063 * } PinMode; 00064 */ 00065 void WS281X::pin_mode_ex(PinName pin, PinMode mode) 00066 { 00067 int port_index = STM_PORT(pin); 00068 int pin_index = STM_PIN(pin); 00069 int offset = pin_index << 1; 00070 GPIO_TypeDef * port_reg = ((GPIO_TypeDef *) (GPIOA_BASE + (port_index << 10))); 00071 00072 // Configure pull-up/pull-down resistors 00073 uint32_t pupd = (uint32_t)mode & 3; 00074 if (pupd > 2) 00075 pupd = 0; // Open-drain = No pull-up/No pull-down 00076 00077 if (mode == OpenDrain) 00078 { 00079 port_reg->PUPDR &= ~(0x3 << offset); // Open-drain = No pull-up/No pull-down 00080 port_reg->OTYPER |= 1 << pin_index; 00081 } 00082 else 00083 { 00084 port_reg->OTYPER &= ~(1 << pin_index); 00085 // pin_mode(pin, mode); 00086 port_reg->PUPDR &= ~(0x3 << offset); 00087 port_reg->PUPDR |= (mode & 0x03) << offset; 00088 } 00089 } 00090 #endif 00091 00092 WS281X::RGBOrder WS281X::rgbOrder(RGBOrder order) 00093 { 00094 switch(_rgb_order = order) 00095 { 00096 case RGB: _1st = 0; _2nd = 1; _3rd = 2; break; // WS2811 00097 case RBG: _1st = 0; _2nd = 2; _3rd = 1; break; 00098 case GRB: _1st = 1; _2nd = 0; _3rd = 2; break; // WS2812 00099 case GBR: _1st = 2; _2nd = 0; _3rd = 1; break; 00100 case BRG: _1st = 1; _2nd = 2; _3rd = 0; break; 00101 case BGR: _1st = 2; _2nd = 1; _3rd = 0; break; 00102 default: 00103 _1st = 0; _2nd = 1; _3rd = 2; 00104 _rgb_order = GRB; // WS2812 00105 break; 00106 } 00107 return _rgb_order; 00108 } 00109 00110 //#define _nop1() __nop() 00111 #define _nop1() do {asm volatile ("nop"); } while(0) 00112 #define _nop2() _nop1(); _nop1() 00113 #define _nop3() _nop1(); _nop2() 00114 #define _nop4() _nop2(); _nop2() 00115 #define _nop5() _nop1(); _nop4() 00116 #define _nop6() _nop2(); _nop4() 00117 #define _nop7() _nop3(); _nop4() 00118 #define _nop8() _nop4(); _nop4() 00119 #define _nop9() _nop1(); _nop8() 00120 #define _nop10() _nop2(); _nop8() 00121 #define _nop11() _nop3(); _nop8() 00122 #define _nop12() _nop4(); _nop8() 00123 #define _nop13() _nop5(); _nop8() 00124 #define _nop14() _nop6(); _nop8() 00125 #define _nop15() _nop7(); _nop8() 00126 #define _nop16() _nop8(); _nop8() 00127 00128 #if defined(TARGET_LPC82X) 00129 // LPCXpresso824-MAX (30MHz) 00130 #define DELAY_T0H() do{ _nop2(); }while(0) 00131 #define DELAY_T1H() do{ _nop6(); }while(0) 00132 #define DELAY_TLOW() do{ _nop6(); }while(0) 00133 #define DELAY_TLOW2() //do{ _nop2(); }while(0) 00134 #define DELAY_SPACE() do{ _nop4(); }while(0) 00135 #define DELAY_NEXT() //do{ _nop1(); }while(0) 00136 #endif 00137 00138 #if defined(TARGET_STM32F0) 00139 // NUCLEO-F030R8 (48MHz) 00140 // NUCLEO-F070RB (48MHz) 00141 // NUCLEO-F072RB (48MHz) 00142 #define DELAY_T0H() do{ _nop8(); _nop4(); }while(0) 00143 #define DELAY_T1H() do{ _nop8(); _nop8(); }while(0) 00144 #define DELAY_TLOW() do{ _nop16(); }while(0) 00145 #define DELAY_TLOW2() //do{ _nop8(); _nop4(); }while(0) 00146 #define DELAY_SPACE() do{ _nop8(); _nop6(); }while(0) 00147 #define DELAY_NEXT() do{ _nop8(); }while(0) 00148 #endif 00149 00150 #if defined(TARGET_NUCLEO_F411RE) 00151 // NUCLEO-F411RE (96MHz) 00152 #define USE_DELAYFUNC 1 00153 #define T0H (10) 00154 #define T0L (31-T0H) 00155 #define T1H (21) 00156 #define T1L (31-T1H) 00157 00158 #define DELAY_T0H() _delay(T0H) 00159 #define DELAY_T1H() _delay(T1H-T0H) 00160 #define DELAY_TLOW() _delay(T1L) 00161 #define DELAY_TLOW2() //DELAY_TLOW() 00162 #define DELAY_SPACE() _delay(T1L-2) 00163 #define DELAY_NEXT() _delay(16) 00164 #endif 00165 00166 #if defined(TARGET_NUCLEO_F446RE) 00167 // NUCLEO-F446RE (180MHz) 00168 #define USE_DELAYFUNC 1 00169 #define T0H (18) 00170 #define T0L (58-T0H) 00171 #define T1H (40) 00172 #define T1L (58-T1H) 00173 00174 #define DELAY_T0H() _delay(T0H) 00175 #define DELAY_T1H() _delay(T1H-T0H) 00176 #define DELAY_TLOW() _delay(T1L) 00177 #define DELAY_TLOW2() //DELAY_TLOW() 00178 #define DELAY_SPACE() _delay(T1L-2) 00179 #define DELAY_NEXT() _delay(16) 00180 #endif 00181 00182 #if defined(TARGET_NUCLEO_F746ZG) 00183 // NUCLEO-F746ZG (216MHz) 00184 #define USE_DELAYFUNC 1 00185 #define T0H (35) 00186 #define T0L (130-T0H) 00187 #define T1H (75) 00188 #define T1L (130-T1H) 00189 00190 #define DELAY_T0H() _delay(T0H) 00191 #define DELAY_T1H() _delay(T1H-T0H) 00192 #define DELAY_TLOW() _delay(T1L) 00193 #define DELAY_TLOW2() //DELAY_TLOW() 00194 #define DELAY_SPACE() _delay(T1L+20) 00195 #define DELAY_NEXT() _delay(50) 00196 #endif 00197 00198 #if defined(TARGET_DISCO_F746NG) 00199 // TARGET_DISCO_F746NG (216MHz) 00200 #define USE_DELAYFUNC 1 00201 #define T0H (35) 00202 #define T0L (125-T0H) 00203 #define T1H (90) 00204 #define T1L (125-T1H) 00205 00206 #define DELAY_T0H() _delay(T0H) 00207 #define DELAY_T1H() _delay(T1H-T0H) 00208 #define DELAY_TLOW() _delay(T1L) 00209 #define DELAY_TLOW2() //DELAY_TLOW() 00210 #define DELAY_SPACE() _delay(T1L-5) 00211 #define DELAY_NEXT() _delay(40) 00212 #endif 00213 00214 #if defined(USE_DELAYFUNC) && (USE_DELAYFUNC != 0) 00215 static inline __attribute__((always_inline)) 00216 void _delay(int value) 00217 { 00218 do { _nop1(); } while (--value); 00219 } 00220 #endif 00221 00222 inline __attribute__((always_inline)) 00223 void WS281X::writeByte(__IO regsize_t *reg_set, __IO regsize_t *reg_clr, regsize_t *mask, uint8_t value) 00224 { 00225 do 00226 { 00227 #if 1 00228 // bit7 00229 *reg_set = mask[0]; 00230 DELAY_T0H(); 00231 *reg_clr = mask[(value >> 7) & 1]; 00232 DELAY_T1H(); 00233 *reg_clr = mask[0]; 00234 DELAY_TLOW(); 00235 00236 // bit6 00237 *reg_set = mask[0]; 00238 DELAY_T0H(); 00239 *reg_clr = mask[(value >> 6) & 1]; 00240 DELAY_T1H(); 00241 *reg_clr = mask[0]; 00242 DELAY_TLOW(); 00243 00244 // bit5 00245 *reg_set = mask[0]; 00246 DELAY_T0H(); 00247 *reg_clr = mask[(value >> 5) & 1]; 00248 DELAY_T1H(); 00249 *reg_clr = mask[0]; 00250 DELAY_TLOW(); 00251 00252 // bit4 00253 *reg_set = mask[0]; 00254 DELAY_T0H(); 00255 *reg_clr = mask[(value >> 4) & 1]; 00256 DELAY_T1H(); 00257 *reg_clr = mask[0]; 00258 DELAY_TLOW(); 00259 #endif 00260 00261 // bit3 00262 *reg_set = mask[0]; 00263 DELAY_T0H(); 00264 *reg_clr = mask[(value >> 3) & 1]; 00265 DELAY_T1H(); 00266 *reg_clr = mask[0]; 00267 DELAY_TLOW(); 00268 00269 // bit2 00270 *reg_set = mask[0]; 00271 DELAY_T0H(); 00272 *reg_clr = mask[(value >> 2) & 1]; 00273 DELAY_T1H(); 00274 *reg_clr = mask[0]; 00275 DELAY_TLOW(); 00276 00277 // bit1 00278 *reg_set = mask[0]; 00279 DELAY_T0H(); 00280 *reg_clr = mask[(value >> 1) & 1]; 00281 DELAY_T1H(); 00282 *reg_clr = mask[0]; 00283 DELAY_TLOW(); 00284 00285 // bit0 00286 *reg_set = mask[0]; 00287 DELAY_T0H(); 00288 *reg_clr = mask[(value >> 0) & 1]; 00289 DELAY_T1H(); 00290 *reg_clr = mask[0]; 00291 DELAY_TLOW2(); 00292 00293 } while (0); 00294 } 00295 00296 void WS281X::show() 00297 { 00298 // CPU_FREQ = 30MHz -> 0.0333us/cycle 00299 // WS2811 0: 0.25us+1.0us, 1: 1.0us+0.25us 00300 // WS2812 0: 0.45us+0.8us, 1: 0.8us+0.45us 00301 00302 if (!_pixels) 00303 return; 00304 00305 #if defined(TARGET_NXP) 00306 __IO uint32_t *reg_set = _gpio.reg_set; 00307 __IO uint32_t *reg_clr = _gpio.reg_clr; 00308 uint32_t mask[2] = { _gpio.mask, 0 }; 00309 #elif defined(TARGET_STM32F0) || defined(TARGET_STM32F1) 00310 __IO uint32_t *reg_set = _gpio.reg_set; 00311 __IO uint32_t *reg_clr = _gpio.reg_clr; 00312 uint32_t mask[2] = { _gpio.mask, 0 }; 00313 #elif defined(TARGET_STM) 00314 __IO uint16_t *reg_set = (__IO uint16_t *)_gpio.reg_set_clr; 00315 __IO uint16_t *reg_clr = reg_set + 1; 00316 uint16_t mask[2] = { _gpio.mask, 0 }; 00317 #endif 00318 00319 uint8_t *pix = (uint8_t *)_pixels; 00320 uint8_t *end = pix + (_num_pixels * sizeof(_pixels[0])); 00321 00322 __disable_irq(); // Disable interrupts temporarily because we don't want our pulse timing to be messed up. 00323 00324 uint8_t value; 00325 do 00326 { 00327 value = pix[_1st]; 00328 writeByte(reg_set, reg_clr, mask, value); 00329 DELAY_SPACE(); 00330 00331 value = pix[_2nd]; 00332 writeByte(reg_set, reg_clr, mask, value); 00333 DELAY_SPACE(); 00334 00335 value = pix[_3rd]; 00336 writeByte(reg_set, reg_clr, mask, value); 00337 pix += sizeof(_pixels[0]); 00338 DELAY_NEXT(); 00339 } while (pix < end); 00340 00341 __enable_irq(); // Re-enable interrupts now that we are done. 00342 00343 //@- wait_us(50); 00344 } 00345 00346 // 指定色でバッファを埋めた後表示 00347 void WS281X::show(const RGBColor color) 00348 { 00349 fill(color); 00350 show(); 00351 } 00352 00353 //---------------------------------------------------------------------------- 00354
Generated on Thu Jul 14 2022 04:31:44 by
1.7.2