Components and supplies
NeoPixel Ring: WS2812 5050 RGB LED
Arduino UNO
Apps and platforms
Arduino IDE
Project description
Code
RX8025.cpp
c_cpp
1#include<stdio.h> 2#include <avr/io.h> 3#include <util/delay.h> 4#include "RX8025.h" 5 6unsigned char ack; /**/ 7 8/******************************************************************* 9 10: void Start_I2c(); 11: I2C ,I2C . 12********************************************************************/ 13void Start_I2c() 14{ 15 SCL_OUT(); 16 SCL_L(); 17 SDA_OUT();/**/ 18 _delay_us(5); 19 SDA_H(); /**/ 20 _delay_us(5); 21 SCL_H(); /**/ 22 _delay_us(6); /*4.7us,*/ 23 SDA_L(); /**/ 24 _delay_us(6); /* 4s*/ 25 SCL_L(); /*I2C */ 26 _delay_us(2); 27} 28/******************************************************************* 29 30: void Stop_I2c(); 31: I2C ,I2C . 32********************************************************************/ 33void Stop_I2c() 34{ 35 SCL_OUT(); 36 SCL_L(); 37 _delay_us(6); 38 SDA_OUT();/**/ 39 SDA_L() ; /**/ 40 _delay_us(6); 41 SCL_H(); /*4s*/ 42 _delay_us(6); 43 SDA_H(); /*I2C */ 44 _delay_us(6); 45 SCL_L(); 46} 47/******************************************************************* 48 49: void SendByte(uchar c); 50: c ,,,, 51.(ack=0 ) 52ack=1; ack=0 53********************************************************************/ 54void SendByte(unsigned char c) 55{ 56 unsigned char BitCnt =0; 57 SCL_OUT(); 58 SDA_OUT();/**/ 59 60 for(BitCnt = 0; BitCnt < 8; BitCnt++){ /*8 */ 61 SCL_L(); 62 _delay_us(6); 63 if((c << BitCnt) & 0x80) SDA_H(); /**/ 64 else SDA_L(); 65 _delay_us(6); 66 SCL_H(); /**/ 67 _delay_us(5); /*4s*/ 68 SCL_L(); 69 _delay_us(6); 70 } 71 SDA_H(); /*8 */ 72 SDA_IN();/**/ 73 _delay_us(1); 74 SCL_H(); 75 _delay_us(3); 76 if(1 == SDA_INPUT()) 77 { 78 ack = 0;/**/ 79 } 80 else ack=1; /**/ 81 SCL_L(); 82 _delay_us(3); 83} 84/******************************************************************* 85 86: uchar RcvByte(); 87: ,() 88 89********************************************************************/ 90unsigned char RcvByte() 91{ 92 unsigned char retc = 0; 93 unsigned char BitCnt = 0; 94 SCL_OUT(); 95 SDA_OUT(); 96 SCL_L(); 97 _delay_us(6); 98 SDA_H(); /**/ 99 _delay_us(2); 100 SDA_IN();/**/ 101 for(BitCnt = 0; BitCnt < 8; BitCnt++) 102 { 103 _delay_us(1); 104 SCL_L(); /**/ 105 _delay_us(6); /*4.7s*/ 106 SCL_H(); /**/ 107 _delay_us(1); 108 retc = (retc << 1); 109 if(1 == SDA_INPUT()) 110 retc = (retc + 1); /*,retc */ 111 } 112 SCL_L(); 113 _delay_us(1); 114 //_delay_us(1); 115 return(retc); 116} 117/******************************************************************** 118 119: void Ack_I2c(bit a); 120:,() 121********************************************************************/ 122void Ack_I2c(unsigned char a) 123{ 124 SDA_OUT(); 125 if(a == 0) SDA_L(); /* */ 126 else SDA_H(); 127 _delay_us(3); 128 SCL_H(); 129 _delay_us(5); /*4s*/ 130 SCL_L(); /*I2C */ 131 _delay_us(2); 132} 133/******************************************************************* 134 135: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); 136: ,, 137slasubas no 1381 139 140********************************************************************/ 141unsigned char ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) 142{ 143 unsigned char i; 144 Start_I2c(); /**/ 145 SendByte(sla); /**/ 146 if(ack == 0) return(0); 147 SendByte(suba); /**/ 148 if(ack == 0) return(0); 149 for(i = 0; i < no; i++){ 150 SendByte(*s); /**/ 151 if(ack == 0) return(0); 152 s++; 153 } 154 Stop_I2c(); /**/ 155 return(1); 156} 157/******************************************************************* 158 159: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); 160: ,, 161slasubas no 1621 163 164********************************************************************/ 165unsigned char IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) 166{ 167 unsigned char i; 168 Start_I2c(); /**/ 169 SendByte(sla); /**/ 170 if(ack == 0) return(0); 171 SendByte(suba); /**/ 172 if(ack == 0) return(0); 173 Start_I2c(); 174 SendByte(sla + 1); 175 if(ack == 0) return(0); 176 for(i = 0; i< no - 1; i++){ 177 *s = RcvByte(); /**/ 178 Ack_I2c(0); /**/ 179 s++; 180 _delay_us(1); 181 _delay_us(1); 182 } 183 *s = RcvByte(); 184 Ack_I2c(1); /**/ 185 Stop_I2c(); /**/ 186 return(1); 187} 188/********************************************************************************************* 189RX8025 190 RX8025_INIT(); 191 192 193 7 194 7unsigned char YY,MO,DD,WW,HH,MM,SS; // 195**********************************************************************************************/ 196void RX8025_INIT(void) 197{ // 198 unsigned char buf[7]; // 199 IRcvStr(RX8025_ADD,RS8025_CONTROL_REG_ADD,buf,2); // 200 if(buf[1] & 0x10){ //C10x01 201 buf[0] |= 0x20; //24 202 buf[1] &= 0xEF; //PON 203 ISendStr(RX8025_ADD,RS8025_CONTROL_REG_ADD,buf,2); // 204 } 205} 206/********************************************************************************************* 207RX8025 208 RX8025_READ(); 209 210 211 ( 212**********************************************************************************************/ 213void RX8025_READ (unsigned char *GetTime) 214{ 215 unsigned char _time[3]; 216 IRcvStr(RX8025_ADD,RS8025_TIME_REG_START_ADD,_time,3); // 217 GetTime[0] = _time[2] >> 4; 218 GetTime[1] = _time[2] & 0x0F; 219 GetTime[2] = _time[1] >> 4; 220 GetTime[3] = _time[1] & 0x0F; 221 GetTime[4] = _time[0] >> 4; 222 GetTime[5] = _time[0] & 0x0F; 223} 224/********************************************************************************************* 225RX8025 226 RX8025_WRITE(); 227 228 229 7 230**********************************************************************************************/ 231void RX8025_WRITE (unsigned char *SetTime) 232{ 233 unsigned char _time[3]; 234 _time[2] = (SetTime[0] << 4) | SetTime[1]; 235 _time[1] = (SetTime[2] << 4) | SetTime[3]; 236 _time[0] = (SetTime[4] << 4) | SetTime[5]; 237 ISendStr(RX8025_ADD,RS8025_TIME_REG_START_ADD,_time,3); // 238} 239
light.cpp
c_cpp
1#include "Adafruit_NeoPixel.h" 2#include "light.h" 3#include "RX8025.h" 4 5extern unsigned char _t[6]; 6 7Adafruit_NeoPixel light[6] = {Adafruit_NeoPixel(10, 13, NEO_GRB + NEO_KHZ800), 8 Adafruit_NeoPixel(10, 12, NEO_GRB + NEO_KHZ800), 9 Adafruit_NeoPixel(10, 11, NEO_GRB + NEO_KHZ800), 10 Adafruit_NeoPixel(10, 10, NEO_GRB + NEO_KHZ800), 11 Adafruit_NeoPixel(10, 9 , NEO_GRB + NEO_KHZ800), 12 Adafruit_NeoPixel(10, 8 , NEO_GRB + NEO_KHZ800)}; 13 14color rgb[6]; 15 16void light_init(){ 17 unsigned char i; 18 for(i=0;i<6;i++)light[i].begin(); 19} 20 21void poeron_effect()// 22{ 23 #define TTT 80 24 #define WHITE 100 25 unsigned char i,j,k; 26 for(k=0;k<2;k++) 27 { 28 for(i=0;i<6;i++) //i 29 { 30 RX8025_READ(_t); 31 light_wirte(_t,rgb); 32 for(j=0;j<_t[i];j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); //j 33 light[i].setPixelColor(_t[i], light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 34 for(j=_t[i]+1;j<10;j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); 35 light[i].show(); 36 for(j=0;j<10;j++)light[i].setPixelColor(j, light[i].Color(0,0,0)); 37 delay(TTT); 38 } 39 for(i=5;i!=255;i--) //i 40 { 41 RX8025_READ(_t); 42 light_wirte(_t,rgb); 43 for(j=0;j<_t[i];j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); //j 44 light[i].setPixelColor(_t[i], light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 45 for(j=_t[i]+1;j<10;j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); 46 light[i].show(); 47 for(j=0;j<10;j++)light[i].setPixelColor(j, light[i].Color(0,0,0)); 48 delay(TTT); 49 } 50 } 51} 52 53void effect4() 54{ 55 static unsigned char n=0,col=0; 56 unsigned char temp,temp1; 57 58 light[temp=n/10].setPixelColor(temp1=n%10, light[n/10].Color(rgb[temp].r,rgb[temp].g,rgb[temp].b)); 59 light[temp=5-temp].setPixelColor(10-temp1, light[n/10].Color(rgb[temp].r,rgb[temp].g,rgb[temp].b)); 60 for(unsigned char i=0;i<6;i++)light[i].show(); 61 for(unsigned char i=0;i<6;i++) 62 for(unsigned char j=0;j<10;j++) 63 light[i].setPixelColor(j, light[i].Color(0,0,0)); 64 n++; 65 if(n==60) 66 { 67 n=0; 68 make_color(&rgb[0],col+=20); 69 for(unsigned char i=1;i<6;i++){ 70 rgb[i] = rgb[0]; 71 } 72 } 73} 74 75void light_wirte(unsigned char* number,color* rgb){ 76 unsigned char i; 77 for(i=0;i<6;i++) 78 light[i].setPixelColor(*(number + i), light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 79 for(i=0;i<6;i++) 80 light[i].show(); 81 for(i=0;i<6;i++) 82 light[i].setPixelColor(*(number + i), light[0].Color(0,0,0)); 83} 84 85/*rgb*/ 86void make_color(color *p,unsigned char c_n) 87{ 88 unsigned char WheelPos; 89 color rgb_temp; 90 WheelPos=255-(((256/8)+c_n)&255); 91 if(WheelPos < 85) 92 { rgb_temp.r=255 - WheelPos * 3;rgb_temp.g=0;rgb_temp.b=WheelPos * 3; 93 *p = rgb_temp; 94 return; 95 } 96 if(WheelPos < 170) 97 { WheelPos -= 85;rgb_temp.r=0;rgb_temp.g=WheelPos * 3;rgb_temp.b=255 - WheelPos * 3; 98 *p = rgb_temp; 99 return; 100 } 101 WheelPos -= 170;rgb_temp.r=WheelPos * 3;rgb_temp.g=255 - WheelPos * 3;rgb_temp.b=0; 102 *p = rgb_temp; 103 return; 104} 105/**/ 106void wheel(color* p) 107{ 108 static unsigned char i=0; 109 unsigned char j,WheelPos; 110 color rgbxxx; 111 for(j=0;j<6;j++) 112 { 113 WheelPos=255-(((j*256/8)+i)&255); 114 if(WheelPos < 85) 115 { rgbxxx.r=255 - WheelPos * 3;rgbxxx.g=0;rgbxxx.b=WheelPos * 3; 116 *(p+j)=rgbxxx; 117 continue; 118 } 119 if(WheelPos < 170) 120 { WheelPos -= 85;rgbxxx.r=0;rgbxxx.g=WheelPos * 3;rgbxxx.b=255 - WheelPos * 3; 121 *(p+j)=rgbxxx; 122 continue; 123 } 124 WheelPos -= 170;rgbxxx.r=WheelPos * 3;rgbxxx.g=255 - WheelPos * 3;rgbxxx.b=0; 125 *(p+j)=rgbxxx; 126 } 127 i++; 128} 129
light.h
c_cpp
1#ifndef LIGHT_H 2#define LIGHT_H 3 4 5struct color{ 6 unsigned char r; 7 unsigned char g; 8 unsigned char b; 9}; 10 11extern color rgb[6]; 12 13void light_init(); 14void poeron_effect(); 15void effect4(); 16void light_wirte(unsigned char* number,color* rgb); 17 18void make_color(color *p,unsigned char c_n); 19void wheel(color* p); 20 21#endif 22
key.h
c_cpp
1/* 2 * key.h 3 * 4 * Created on: 201858 5 * Author: 6 */ 7 8 #ifndef _KEY_H 9 #define _KEY_H 10 11 //#define key_input(nnn) (PIND>>(5+nnn)) & 0x01 12unsigned char key_input(unsigned char nnn); 13 #define key_no 0 //no keys 14 #define key_click 1 //click keys 15 #define key_double 2 //double click 16 #define key_long 3 //long click 17 18 #define key_state_0 0 19 #define key_state_1 1 20 #define key_state_2 2 21 #define key_state_3 3 //key states define 22 23 #define key_flag (1<<0) 24 #define clear_key_flag (~(1<<0)) 25 void key_init(); // 26 unsigned char key_read(unsigned char nnn); // 27 28 #endif /*end _KEY_H*/ 29
Adafruit_NeoPixel.cpp
c_cpp
1/*------------------------------------------------------------------------- 2 Arduino library to control a wide variety of WS2811- and WS2812-based RGB 3 LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips. 4 Currently handles 400 and 800 KHz bitstreams on 8, 12 and 16 MHz ATmega 5 MCUs, with LEDs wired for various color orders. Handles most output pins 6 (possible exception with upper PORT registers on the Arduino Mega). 7 8 Written by Phil Burgess / Paint Your Dragon for Adafruit Industries, 9 contributions by PJRC, Michael Miller and other members of the open 10 source community. 11 12 Adafruit invests time and resources providing this open source code, 13 please support Adafruit and open-source hardware by purchasing products 14 from Adafruit! 15 16 ------------------------------------------------------------------------- 17 This file is part of the Adafruit NeoPixel library. 18 19 NeoPixel is free software: you can redistribute it and/or modify 20 it under the terms of the GNU Lesser General Public License as 21 published by the Free Software Foundation, either version 3 of 22 the License, or (at your option) any later version. 23 24 NeoPixel is distributed in the hope that it will be useful, 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 GNU Lesser General Public License for more details. 28 29 You should have received a copy of the GNU Lesser General Public 30 License along with NeoPixel. If not, see 31 <http://www.gnu.org/licenses/>. 32 -------------------------------------------------------------------------*/ 33 34#include "Adafruit_NeoPixel.h" 35 36#if defined(NRF52) 37#include "nrf.h" 38 39// Interrupt is only disabled if there is no PWM device available 40// Note: Adafruit Bluefruit nrf52 does not use this option 41//#define NRF52_DISABLE_INT 42#endif 43 44// Constructor when length, pin and type are known at compile-time: 45Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, uint8_t p, neoPixelType t) : 46 begun(false), brightness(0), pixels(NULL), endTime(0) 47{ 48 updateType(t); 49 updateLength(n); 50 setPin(p); 51} 52 53// via Michael Vogt/neophob: empty constructor is used when strand length 54// isn't known at compile-time; situations where program config might be 55// read from internal flash memory or an SD card, or arrive via serial 56// command. If using this constructor, MUST follow up with updateType(), 57// updateLength(), etc. to establish the strand type, length and pin number! 58Adafruit_NeoPixel::Adafruit_NeoPixel() : 59#ifdef NEO_KHZ400 60 is800KHz(true), 61#endif 62 begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0), pixels(NULL), 63 rOffset(1), gOffset(0), bOffset(2), wOffset(1), endTime(0) 64{ 65} 66 67Adafruit_NeoPixel::~Adafruit_NeoPixel() { 68 if(pixels) free(pixels); 69 if(pin >= 0) pinMode(pin, INPUT); 70} 71 72void Adafruit_NeoPixel::begin(void) { 73 if(pin >= 0) { 74 pinMode(pin, OUTPUT); 75 digitalWrite(pin, LOW); 76 } 77 begun = true; 78 79} 80 81void Adafruit_NeoPixel::updateLength(uint16_t n) { 82 if(pixels) free(pixels); // Free existing data (if any) 83 84 // Allocate new data -- note: ALL PIXELS ARE CLEARED 85 numBytes = n * ((wOffset == rOffset) ? 3 : 4); 86 if((pixels = (uint8_t *)malloc(numBytes))) { 87 memset(pixels, 0, numBytes); 88 numLEDs = n; 89 } else { 90 numLEDs = numBytes = 0; 91 } 92} 93 94void Adafruit_NeoPixel::updateType(neoPixelType t) { 95 boolean oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW 96 97 wOffset = (t >> 6) & 0b11; // See notes in header file 98 rOffset = (t >> 4) & 0b11; // regarding R/G/B/W offsets 99 gOffset = (t >> 2) & 0b11; 100 bOffset = t & 0b11; 101#ifdef NEO_KHZ400 102 is800KHz = (t < 256); // 400 KHz flag is 1<<8 103#endif 104 105 // If bytes-per-pixel has changed (and pixel data was previously 106 // allocated), re-allocate to new size. Will clear any data. 107 if(pixels) { 108 boolean newThreeBytesPerPixel = (wOffset == rOffset); 109 if(newThreeBytesPerPixel != oldThreeBytesPerPixel) updateLength(numLEDs); 110 } 111} 112 113#if defined(ESP8266) 114// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution 115extern "C" void ICACHE_RAM_ATTR espShow( 116 uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type); 117#elif defined(ESP32) 118extern "C" void espShow( 119 uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type); 120#endif // ESP8266 121 122void Adafruit_NeoPixel::show(void) { 123 124 if(!pixels) return; 125 126 // Data latch = 300+ microsecond pause in the output stream. Rather than 127 // put a delay at the end of the function, the ending time is noted and 128 // the function will simply hold off (if needed) on issuing the 129 // subsequent round of data until the latch time has elapsed. This 130 // allows the mainline code to start generating the next frame of data 131 // rather than stalling for the latch. 132 while(!canShow()); 133 // endTime is a private member (rather than global var) so that multiple 134 // instances on different pins can be quickly issued in succession (each 135 // instance doesn't delay the next). 136 137 // In order to make this code runtime-configurable to work with any pin, 138 // SBI/CBI instructions are eschewed in favor of full PORT writes via the 139 // OUT or ST instructions. It relies on two facts: that peripheral 140 // functions (such as PWM) take precedence on output pins, so our PORT- 141 // wide writes won't interfere, and that interrupts are globally disabled 142 // while data is being issued to the LEDs, so no other code will be 143 // accessing the PORT. The code takes an initial 'snapshot' of the PORT 144 // state, computes 'pin high' and 'pin low' values, and writes these back 145 // to the PORT register as needed. 146 147 // NRF52 may use PWM + DMA (if available), may not need to disable interrupt 148#ifndef NRF52 149 noInterrupts(); // Need 100% focus on instruction timing 150#endif 151 152#ifdef __AVR__ 153// AVR MCUs -- ATmega & ATtiny (no XMEGA) --------------------------------- 154 155 volatile uint16_t 156 i = numBytes; // Loop counter 157 volatile uint8_t 158 *ptr = pixels, // Pointer to next byte 159 b = *ptr++, // Current byte value 160 hi, // PORT w/output bit set high 161 lo; // PORT w/output bit set low 162 163 // Hand-tuned assembly code issues data to the LED drivers at a specific 164 // rate. There's separate code for different CPU speeds (8, 12, 16 MHz) 165 // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The 166 // datastream timing for the LED drivers allows a little wiggle room each 167 // way (listed in the datasheets), so the conditions for compiling each 168 // case are set up for a range of frequencies rather than just the exact 169 // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on 170 // devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based 171 // on the datasheet figures and have not been extensively tested outside 172 // the canonical 8/12/16 MHz speeds; there's no guarantee these will work 173 // close to the extremes (or possibly they could be pushed further). 174 // Keep in mind only one CPU speed case actually gets compiled; the 175 // resulting program isn't as massive as it might look from source here. 176 177// 8 MHz(ish) AVR --------------------------------------------------------- 178#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) 179 180#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 181 if(is800KHz) { 182#endif 183 184 volatile uint8_t n1, n2 = 0; // First, next bits out 185 186 // Squeezing an 800 KHz stream out of an 8 MHz chip requires code 187 // specific to each PORT register. 188 189 // 10 instruction clocks per bit: HHxxxxxLLL 190 // OUT instructions: ^ ^ ^ (T=0,2,7) 191 192 // PORTD OUTPUT ---------------------------------------------------- 193 194#if defined(PORTD) 195 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 196 if(port == &PORTD) { 197 #endif // defined(PORTB/C/F) 198 199 hi = PORTD | pinMask; 200 lo = PORTD & ~pinMask; 201 n1 = lo; 202 if(b & 0x80) n1 = hi; 203 204 // Dirty trick: RJMPs proceeding to the next instruction are used 205 // to delay two clock cycles in one instruction word (rather than 206 // using two NOPs). This was necessary in order to squeeze the 207 // loop down to exactly 64 words -- the maximum possible for a 208 // relative branch. 209 210 asm volatile( 211 "headD:" "\ 212\ " // Clk Pseudocode 213 // Bit 7: 214 "out %[port] , %[hi]" "\ 215\ " // 1 PORT = hi 216 "mov %[n2] , %[lo]" "\ 217\ " // 1 n2 = lo 218 "out %[port] , %[n1]" "\ 219\ " // 1 PORT = n1 220 "rjmp .+0" "\ 221\ " // 2 nop nop 222 "sbrc %[byte] , 6" "\ 223\ " // 1-2 if(b & 0x40) 224 "mov %[n2] , %[hi]" "\ 225\ " // 0-1 n2 = hi 226 "out %[port] , %[lo]" "\ 227\ " // 1 PORT = lo 228 "rjmp .+0" "\ 229\ " // 2 nop nop 230 // Bit 6: 231 "out %[port] , %[hi]" "\ 232\ " // 1 PORT = hi 233 "mov %[n1] , %[lo]" "\ 234\ " // 1 n1 = lo 235 "out %[port] , %[n2]" "\ 236\ " // 1 PORT = n2 237 "rjmp .+0" "\ 238\ " // 2 nop nop 239 "sbrc %[byte] , 5" "\ 240\ " // 1-2 if(b & 0x20) 241 "mov %[n1] , %[hi]" "\ 242\ " // 0-1 n1 = hi 243 "out %[port] , %[lo]" "\ 244\ " // 1 PORT = lo 245 "rjmp .+0" "\ 246\ " // 2 nop nop 247 // Bit 5: 248 "out %[port] , %[hi]" "\ 249\ " // 1 PORT = hi 250 "mov %[n2] , %[lo]" "\ 251\ " // 1 n2 = lo 252 "out %[port] , %[n1]" "\ 253\ " // 1 PORT = n1 254 "rjmp .+0" "\ 255\ " // 2 nop nop 256 "sbrc %[byte] , 4" "\ 257\ " // 1-2 if(b & 0x10) 258 "mov %[n2] , %[hi]" "\ 259\ " // 0-1 n2 = hi 260 "out %[port] , %[lo]" "\ 261\ " // 1 PORT = lo 262 "rjmp .+0" "\ 263\ " // 2 nop nop 264 // Bit 4: 265 "out %[port] , %[hi]" "\ 266\ " // 1 PORT = hi 267 "mov %[n1] , %[lo]" "\ 268\ " // 1 n1 = lo 269 "out %[port] , %[n2]" "\ 270\ " // 1 PORT = n2 271 "rjmp .+0" "\ 272\ " // 2 nop nop 273 "sbrc %[byte] , 3" "\ 274\ " // 1-2 if(b & 0x08) 275 "mov %[n1] , %[hi]" "\ 276\ " // 0-1 n1 = hi 277 "out %[port] , %[lo]" "\ 278\ " // 1 PORT = lo 279 "rjmp .+0" "\ 280\ " // 2 nop nop 281 // Bit 3: 282 "out %[port] , %[hi]" "\ 283\ " // 1 PORT = hi 284 "mov %[n2] , %[lo]" "\ 285\ " // 1 n2 = lo 286 "out %[port] , %[n1]" "\ 287\ " // 1 PORT = n1 288 "rjmp .+0" "\ 289\ " // 2 nop nop 290 "sbrc %[byte] , 2" "\ 291\ " // 1-2 if(b & 0x04) 292 "mov %[n2] , %[hi]" "\ 293\ " // 0-1 n2 = hi 294 "out %[port] , %[lo]" "\ 295\ " // 1 PORT = lo 296 "rjmp .+0" "\ 297\ " // 2 nop nop 298 // Bit 2: 299 "out %[port] , %[hi]" "\ 300\ " // 1 PORT = hi 301 "mov %[n1] , %[lo]" "\ 302\ " // 1 n1 = lo 303 "out %[port] , %[n2]" "\ 304\ " // 1 PORT = n2 305 "rjmp .+0" "\ 306\ " // 2 nop nop 307 "sbrc %[byte] , 1" "\ 308\ " // 1-2 if(b & 0x02) 309 "mov %[n1] , %[hi]" "\ 310\ " // 0-1 n1 = hi 311 "out %[port] , %[lo]" "\ 312\ " // 1 PORT = lo 313 "rjmp .+0" "\ 314\ " // 2 nop nop 315 // Bit 1: 316 "out %[port] , %[hi]" "\ 317\ " // 1 PORT = hi 318 "mov %[n2] , %[lo]" "\ 319\ " // 1 n2 = lo 320 "out %[port] , %[n1]" "\ 321\ " // 1 PORT = n1 322 "rjmp .+0" "\ 323\ " // 2 nop nop 324 "sbrc %[byte] , 0" "\ 325\ " // 1-2 if(b & 0x01) 326 "mov %[n2] , %[hi]" "\ 327\ " // 0-1 n2 = hi 328 "out %[port] , %[lo]" "\ 329\ " // 1 PORT = lo 330 "sbiw %[count], 1" "\ 331\ " // 2 i-- (don't act on Z flag yet) 332 // Bit 0: 333 "out %[port] , %[hi]" "\ 334\ " // 1 PORT = hi 335 "mov %[n1] , %[lo]" "\ 336\ " // 1 n1 = lo 337 "out %[port] , %[n2]" "\ 338\ " // 1 PORT = n2 339 "ld %[byte] , %a[ptr]+" "\ 340\ " // 2 b = *ptr++ 341 "sbrc %[byte] , 7" "\ 342\ " // 1-2 if(b & 0x80) 343 "mov %[n1] , %[hi]" "\ 344\ " // 0-1 n1 = hi 345 "out %[port] , %[lo]" "\ 346\ " // 1 PORT = lo 347 "brne headD" "\ 348" // 2 while(i) (Z flag set above) 349 : [byte] "+r" (b), 350 [n1] "+r" (n1), 351 [n2] "+r" (n2), 352 [count] "+w" (i) 353 : [port] "I" (_SFR_IO_ADDR(PORTD)), 354 [ptr] "e" (ptr), 355 [hi] "r" (hi), 356 [lo] "r" (lo)); 357 358 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 359 } else // other PORT(s) 360 #endif // defined(PORTB/C/F) 361#endif // defined(PORTD) 362 363 // PORTB OUTPUT ---------------------------------------------------- 364 365#if defined(PORTB) 366 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 367 if(port == &PORTB) { 368 #endif // defined(PORTD/C/F) 369 370 // Same as above, just switched to PORTB and stripped of comments. 371 hi = PORTB | pinMask; 372 lo = PORTB & ~pinMask; 373 n1 = lo; 374 if(b & 0x80) n1 = hi; 375 376 asm volatile( 377 "headB:" "\ 378\ " 379 "out %[port] , %[hi]" "\ 380\ " 381 "mov %[n2] , %[lo]" "\ 382\ " 383 "out %[port] , %[n1]" "\ 384\ " 385 "rjmp .+0" "\ 386\ " 387 "sbrc %[byte] , 6" "\ 388\ " 389 "mov %[n2] , %[hi]" "\ 390\ " 391 "out %[port] , %[lo]" "\ 392\ " 393 "rjmp .+0" "\ 394\ " 395 "out %[port] , %[hi]" "\ 396\ " 397 "mov %[n1] , %[lo]" "\ 398\ " 399 "out %[port] , %[n2]" "\ 400\ " 401 "rjmp .+0" "\ 402\ " 403 "sbrc %[byte] , 5" "\ 404\ " 405 "mov %[n1] , %[hi]" "\ 406\ " 407 "out %[port] , %[lo]" "\ 408\ " 409 "rjmp .+0" "\ 410\ " 411 "out %[port] , %[hi]" "\ 412\ " 413 "mov %[n2] , %[lo]" "\ 414\ " 415 "out %[port] , %[n1]" "\ 416\ " 417 "rjmp .+0" "\ 418\ " 419 "sbrc %[byte] , 4" "\ 420\ " 421 "mov %[n2] , %[hi]" "\ 422\ " 423 "out %[port] , %[lo]" "\ 424\ " 425 "rjmp .+0" "\ 426\ " 427 "out %[port] , %[hi]" "\ 428\ " 429 "mov %[n1] , %[lo]" "\ 430\ " 431 "out %[port] , %[n2]" "\ 432\ " 433 "rjmp .+0" "\ 434\ " 435 "sbrc %[byte] , 3" "\ 436\ " 437 "mov %[n1] , %[hi]" "\ 438\ " 439 "out %[port] , %[lo]" "\ 440\ " 441 "rjmp .+0" "\ 442\ " 443 "out %[port] , %[hi]" "\ 444\ " 445 "mov %[n2] , %[lo]" "\ 446\ " 447 "out %[port] , %[n1]" "\ 448\ " 449 "rjmp .+0" "\ 450\ " 451 "sbrc %[byte] , 2" "\ 452\ " 453 "mov %[n2] , %[hi]" "\ 454\ " 455 "out %[port] , %[lo]" "\ 456\ " 457 "rjmp .+0" "\ 458\ " 459 "out %[port] , %[hi]" "\ 460\ " 461 "mov %[n1] , %[lo]" "\ 462\ " 463 "out %[port] , %[n2]" "\ 464\ " 465 "rjmp .+0" "\ 466\ " 467 "sbrc %[byte] , 1" "\ 468\ " 469 "mov %[n1] , %[hi]" "\ 470\ " 471 "out %[port] , %[lo]" "\ 472\ " 473 "rjmp .+0" "\ 474\ " 475 "out %[port] , %[hi]" "\ 476\ " 477 "mov %[n2] , %[lo]" "\ 478\ " 479 "out %[port] , %[n1]" "\ 480\ " 481 "rjmp .+0" "\ 482\ " 483 "sbrc %[byte] , 0" "\ 484\ " 485 "mov %[n2] , %[hi]" "\ 486\ " 487 "out %[port] , %[lo]" "\ 488\ " 489 "sbiw %[count], 1" "\ 490\ " 491 "out %[port] , %[hi]" "\ 492\ " 493 "mov %[n1] , %[lo]" "\ 494\ " 495 "out %[port] , %[n2]" "\ 496\ " 497 "ld %[byte] , %a[ptr]+" "\ 498\ " 499 "sbrc %[byte] , 7" "\ 500\ " 501 "mov %[n1] , %[hi]" "\ 502\ " 503 "out %[port] , %[lo]" "\ 504\ " 505 "brne headB" "\ 506" 507 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 508 : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), 509 [lo] "r" (lo)); 510 511 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 512 } 513 #endif 514 #if defined(PORTC) || defined(PORTF) 515 else 516 #endif // defined(PORTC/F) 517#endif // defined(PORTB) 518 519 // PORTC OUTPUT ---------------------------------------------------- 520 521#if defined(PORTC) 522 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 523 if(port == &PORTC) { 524 #endif // defined(PORTD/B/F) 525 526 // Same as above, just switched to PORTC and stripped of comments. 527 hi = PORTC | pinMask; 528 lo = PORTC & ~pinMask; 529 n1 = lo; 530 if(b & 0x80) n1 = hi; 531 532 asm volatile( 533 "headC:" "\ 534\ " 535 "out %[port] , %[hi]" "\ 536\ " 537 "mov %[n2] , %[lo]" "\ 538\ " 539 "out %[port] , %[n1]" "\ 540\ " 541 "rjmp .+0" "\ 542\ " 543 "sbrc %[byte] , 6" "\ 544\ " 545 "mov %[n2] , %[hi]" "\ 546\ " 547 "out %[port] , %[lo]" "\ 548\ " 549 "rjmp .+0" "\ 550\ " 551 "out %[port] , %[hi]" "\ 552\ " 553 "mov %[n1] , %[lo]" "\ 554\ " 555 "out %[port] , %[n2]" "\ 556\ " 557 "rjmp .+0" "\ 558\ " 559 "sbrc %[byte] , 5" "\ 560\ " 561 "mov %[n1] , %[hi]" "\ 562\ " 563 "out %[port] , %[lo]" "\ 564\ " 565 "rjmp .+0" "\ 566\ " 567 "out %[port] , %[hi]" "\ 568\ " 569 "mov %[n2] , %[lo]" "\ 570\ " 571 "out %[port] , %[n1]" "\ 572\ " 573 "rjmp .+0" "\ 574\ " 575 "sbrc %[byte] , 4" "\ 576\ " 577 "mov %[n2] , %[hi]" "\ 578\ " 579 "out %[port] , %[lo]" "\ 580\ " 581 "rjmp .+0" "\ 582\ " 583 "out %[port] , %[hi]" "\ 584\ " 585 "mov %[n1] , %[lo]" "\ 586\ " 587 "out %[port] , %[n2]" "\ 588\ " 589 "rjmp .+0" "\ 590\ " 591 "sbrc %[byte] , 3" "\ 592\ " 593 "mov %[n1] , %[hi]" "\ 594\ " 595 "out %[port] , %[lo]" "\ 596\ " 597 "rjmp .+0" "\ 598\ " 599 "out %[port] , %[hi]" "\ 600\ " 601 "mov %[n2] , %[lo]" "\ 602\ " 603 "out %[port] , %[n1]" "\ 604\ " 605 "rjmp .+0" "\ 606\ " 607 "sbrc %[byte] , 2" "\ 608\ " 609 "mov %[n2] , %[hi]" "\ 610\ " 611 "out %[port] , %[lo]" "\ 612\ " 613 "rjmp .+0" "\ 614\ " 615 "out %[port] , %[hi]" "\ 616\ " 617 "mov %[n1] , %[lo]" "\ 618\ " 619 "out %[port] , %[n2]" "\ 620\ " 621 "rjmp .+0" "\ 622\ " 623 "sbrc %[byte] , 1" "\ 624\ " 625 "mov %[n1] , %[hi]" "\ 626\ " 627 "out %[port] , %[lo]" "\ 628\ " 629 "rjmp .+0" "\ 630\ " 631 "out %[port] , %[hi]" "\ 632\ " 633 "mov %[n2] , %[lo]" "\ 634\ " 635 "out %[port] , %[n1]" "\ 636\ " 637 "rjmp .+0" "\ 638\ " 639 "sbrc %[byte] , 0" "\ 640\ " 641 "mov %[n2] , %[hi]" "\ 642\ " 643 "out %[port] , %[lo]" "\ 644\ " 645 "sbiw %[count], 1" "\ 646\ " 647 "out %[port] , %[hi]" "\ 648\ " 649 "mov %[n1] , %[lo]" "\ 650\ " 651 "out %[port] , %[n2]" "\ 652\ " 653 "ld %[byte] , %a[ptr]+" "\ 654\ " 655 "sbrc %[byte] , 7" "\ 656\ " 657 "mov %[n1] , %[hi]" "\ 658\ " 659 "out %[port] , %[lo]" "\ 660\ " 661 "brne headC" "\ 662" 663 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 664 : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi), 665 [lo] "r" (lo)); 666 667 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 668 } 669 #endif // defined(PORTD/B/F) 670 #if defined(PORTF) 671 else 672 #endif 673#endif // defined(PORTC) 674 675 // PORTF OUTPUT ---------------------------------------------------- 676 677#if defined(PORTF) 678 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 679 if(port == &PORTF) { 680 #endif // defined(PORTD/B/C) 681 682 hi = PORTF | pinMask; 683 lo = PORTF & ~pinMask; 684 n1 = lo; 685 if(b & 0x80) n1 = hi; 686 687 asm volatile( 688 "headF:" "\ 689\ " 690 "out %[port] , %[hi]" "\ 691\ " 692 "mov %[n2] , %[lo]" "\ 693\ " 694 "out %[port] , %[n1]" "\ 695\ " 696 "rjmp .+0" "\ 697\ " 698 "sbrc %[byte] , 6" "\ 699\ " 700 "mov %[n2] , %[hi]" "\ 701\ " 702 "out %[port] , %[lo]" "\ 703\ " 704 "rjmp .+0" "\ 705\ " 706 "out %[port] , %[hi]" "\ 707\ " 708 "mov %[n1] , %[lo]" "\ 709\ " 710 "out %[port] , %[n2]" "\ 711\ " 712 "rjmp .+0" "\ 713\ " 714 "sbrc %[byte] , 5" "\ 715\ " 716 "mov %[n1] , %[hi]" "\ 717\ " 718 "out %[port] , %[lo]" "\ 719\ " 720 "rjmp .+0" "\ 721\ " 722 "out %[port] , %[hi]" "\ 723\ " 724 "mov %[n2] , %[lo]" "\ 725\ " 726 "out %[port] , %[n1]" "\ 727\ " 728 "rjmp .+0" "\ 729\ " 730 "sbrc %[byte] , 4" "\ 731\ " 732 "mov %[n2] , %[hi]" "\ 733\ " 734 "out %[port] , %[lo]" "\ 735\ " 736 "rjmp .+0" "\ 737\ " 738 "out %[port] , %[hi]" "\ 739\ " 740 "mov %[n1] , %[lo]" "\ 741\ " 742 "out %[port] , %[n2]" "\ 743\ " 744 "rjmp .+0" "\ 745\ " 746 "sbrc %[byte] , 3" "\ 747\ " 748 "mov %[n1] , %[hi]" "\ 749\ " 750 "out %[port] , %[lo]" "\ 751\ " 752 "rjmp .+0" "\ 753\ " 754 "out %[port] , %[hi]" "\ 755\ " 756 "mov %[n2] , %[lo]" "\ 757\ " 758 "out %[port] , %[n1]" "\ 759\ " 760 "rjmp .+0" "\ 761\ " 762 "sbrc %[byte] , 2" "\ 763\ " 764 "mov %[n2] , %[hi]" "\ 765\ " 766 "out %[port] , %[lo]" "\ 767\ " 768 "rjmp .+0" "\ 769\ " 770 "out %[port] , %[hi]" "\ 771\ " 772 "mov %[n1] , %[lo]" "\ 773\ " 774 "out %[port] , %[n2]" "\ 775\ " 776 "rjmp .+0" "\ 777\ " 778 "sbrc %[byte] , 1" "\ 779\ " 780 "mov %[n1] , %[hi]" "\ 781\ " 782 "out %[port] , %[lo]" "\ 783\ " 784 "rjmp .+0" "\ 785\ " 786 "out %[port] , %[hi]" "\ 787\ " 788 "mov %[n2] , %[lo]" "\ 789\ " 790 "out %[port] , %[n1]" "\ 791\ " 792 "rjmp .+0" "\ 793\ " 794 "sbrc %[byte] , 0" "\ 795\ " 796 "mov %[n2] , %[hi]" "\ 797\ " 798 "out %[port] , %[lo]" "\ 799\ " 800 "sbiw %[count], 1" "\ 801\ " 802 "out %[port] , %[hi]" "\ 803\ " 804 "mov %[n1] , %[lo]" "\ 805\ " 806 "out %[port] , %[n2]" "\ 807\ " 808 "ld %[byte] , %a[ptr]+" "\ 809\ " 810 "sbrc %[byte] , 7" "\ 811\ " 812 "mov %[n1] , %[hi]" "\ 813\ " 814 "out %[port] , %[lo]" "\ 815\ " 816 "brne headF" "\ 817" 818 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 819 : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi), 820 [lo] "r" (lo)); 821 822 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 823 } 824 #endif // defined(PORTD/B/C) 825#endif // defined(PORTF) 826 827#ifdef NEO_KHZ400 828 } else { // end 800 KHz, do 400 KHz 829 830 // Timing is more relaxed; unrolling the inner loop for each bit is 831 // not necessary. Still using the peculiar RJMPs as 2X NOPs, not out 832 // of need but just to trim the code size down a little. 833 // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical 834 // to the 800-on-16 code later -- the hi/lo timing between WS2811 and 835 // WS2812 is not simply a 2:1 scale! 836 837 // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL 838 // ST instructions: ^ ^ ^ (T=0,4,10) 839 840 volatile uint8_t next, bit; 841 842 hi = *port | pinMask; 843 lo = *port & ~pinMask; 844 next = lo; 845 bit = 8; 846 847 asm volatile( 848 "head20:" "\ 849\ " // Clk Pseudocode (T = 0) 850 "st %a[port], %[hi]" "\ 851\ " // 2 PORT = hi (T = 2) 852 "sbrc %[byte] , 7" "\ 853\ " // 1-2 if(b & 128) 854 "mov %[next], %[hi]" "\ 855\ " // 0-1 next = hi (T = 4) 856 "st %a[port], %[next]" "\ 857\ " // 2 PORT = next (T = 6) 858 "mov %[next] , %[lo]" "\ 859\ " // 1 next = lo (T = 7) 860 "dec %[bit]" "\ 861\ " // 1 bit-- (T = 8) 862 "breq nextbyte20" "\ 863\ " // 1-2 if(bit == 0) 864 "rol %[byte]" "\ 865\ " // 1 b <<= 1 (T = 10) 866 "st %a[port], %[lo]" "\ 867\ " // 2 PORT = lo (T = 12) 868 "rjmp .+0" "\ 869\ " // 2 nop nop (T = 14) 870 "rjmp .+0" "\ 871\ " // 2 nop nop (T = 16) 872 "rjmp .+0" "\ 873\ " // 2 nop nop (T = 18) 874 "rjmp head20" "\ 875\ " // 2 -> head20 (next bit out) 876 "nextbyte20:" "\ 877\ " // (T = 10) 878 "st %a[port], %[lo]" "\ 879\ " // 2 PORT = lo (T = 12) 880 "nop" "\ 881\ " // 1 nop (T = 13) 882 "ldi %[bit] , 8" "\ 883\ " // 1 bit = 8 (T = 14) 884 "ld %[byte] , %a[ptr]+" "\ 885\ " // 2 b = *ptr++ (T = 16) 886 "sbiw %[count], 1" "\ 887\ " // 2 i-- (T = 18) 888 "brne head20" "\ 889" // 2 if(i != 0) -> (next byte) 890 : [port] "+e" (port), 891 [byte] "+r" (b), 892 [bit] "+r" (bit), 893 [next] "+r" (next), 894 [count] "+w" (i) 895 : [hi] "r" (hi), 896 [lo] "r" (lo), 897 [ptr] "e" (ptr)); 898 } 899#endif // NEO_KHZ400 900 901// 12 MHz(ish) AVR -------------------------------------------------------- 902#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) 903 904#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 905 if(is800KHz) { 906#endif 907 908 // In the 12 MHz case, an optimized 800 KHz datastream (no dead time 909 // between bytes) requires a PORT-specific loop similar to the 8 MHz 910 // code (but a little more relaxed in this case). 911 912 // 15 instruction clocks per bit: HHHHxxxxxxLLLLL 913 // OUT instructions: ^ ^ ^ (T=0,4,10) 914 915 volatile uint8_t next; 916 917 // PORTD OUTPUT ---------------------------------------------------- 918 919#if defined(PORTD) 920 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 921 if(port == &PORTD) { 922 #endif // defined(PORTB/C/F) 923 924 hi = PORTD | pinMask; 925 lo = PORTD & ~pinMask; 926 next = lo; 927 if(b & 0x80) next = hi; 928 929 // Don't "optimize" the OUT calls into the bitTime subroutine; 930 // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs! 931 asm volatile( 932 "headD:" "\ 933\ " // (T = 0) 934 "out %[port], %[hi]" "\ 935\ " // (T = 1) 936 "rcall bitTimeD" "\ 937\ " // Bit 7 (T = 15) 938 "out %[port], %[hi]" "\ 939\ " 940 "rcall bitTimeD" "\ 941\ " // Bit 6 942 "out %[port], %[hi]" "\ 943\ " 944 "rcall bitTimeD" "\ 945\ " // Bit 5 946 "out %[port], %[hi]" "\ 947\ " 948 "rcall bitTimeD" "\ 949\ " // Bit 4 950 "out %[port], %[hi]" "\ 951\ " 952 "rcall bitTimeD" "\ 953\ " // Bit 3 954 "out %[port], %[hi]" "\ 955\ " 956 "rcall bitTimeD" "\ 957\ " // Bit 2 958 "out %[port], %[hi]" "\ 959\ " 960 "rcall bitTimeD" "\ 961\ " // Bit 1 962 // Bit 0: 963 "out %[port] , %[hi]" "\ 964\ " // 1 PORT = hi (T = 1) 965 "rjmp .+0" "\ 966\ " // 2 nop nop (T = 3) 967 "ld %[byte] , %a[ptr]+" "\ 968\ " // 2 b = *ptr++ (T = 5) 969 "out %[port] , %[next]" "\ 970\ " // 1 PORT = next (T = 6) 971 "mov %[next] , %[lo]" "\ 972\ " // 1 next = lo (T = 7) 973 "sbrc %[byte] , 7" "\ 974\ " // 1-2 if(b & 0x80) (T = 8) 975 "mov %[next] , %[hi]" "\ 976\ " // 0-1 next = hi (T = 9) 977 "nop" "\ 978\ " // 1 (T = 10) 979 "out %[port] , %[lo]" "\ 980\ " // 1 PORT = lo (T = 11) 981 "sbiw %[count], 1" "\ 982\ " // 2 i-- (T = 13) 983 "brne headD" "\ 984\ " // 2 if(i != 0) -> (next byte) 985 "rjmp doneD" "\ 986\ " 987 "bitTimeD:" "\ 988\ " // nop nop nop (T = 4) 989 "out %[port], %[next]" "\ 990\ " // 1 PORT = next (T = 5) 991 "mov %[next], %[lo]" "\ 992\ " // 1 next = lo (T = 6) 993 "rol %[byte]" "\ 994\ " // 1 b <<= 1 (T = 7) 995 "sbrc %[byte], 7" "\ 996\ " // 1-2 if(b & 0x80) (T = 8) 997 "mov %[next], %[hi]" "\ 998\ " // 0-1 next = hi (T = 9) 999 "nop" "\ 1000\ " // 1 (T = 10) 1001 "out %[port], %[lo]" "\ 1002\ " // 1 PORT = lo (T = 11) 1003 "ret" "\ 1004\ " // 4 nop nop nop nop (T = 15) 1005 "doneD:" "\ 1006" 1007 : [byte] "+r" (b), 1008 [next] "+r" (next), 1009 [count] "+w" (i) 1010 : [port] "I" (_SFR_IO_ADDR(PORTD)), 1011 [ptr] "e" (ptr), 1012 [hi] "r" (hi), 1013 [lo] "r" (lo)); 1014 1015 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 1016 } else // other PORT(s) 1017 #endif // defined(PORTB/C/F) 1018#endif // defined(PORTD) 1019 1020 // PORTB OUTPUT ---------------------------------------------------- 1021 1022#if defined(PORTB) 1023 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 1024 if(port == &PORTB) { 1025 #endif // defined(PORTD/C/F) 1026 1027 hi = PORTB | pinMask; 1028 lo = PORTB & ~pinMask; 1029 next = lo; 1030 if(b & 0x80) next = hi; 1031 1032 // Same as above, just set for PORTB & stripped of comments 1033 asm volatile( 1034 "headB:" "\ 1035\ " 1036 "out %[port], %[hi]" "\ 1037\ " 1038 "rcall bitTimeB" "\ 1039\ " 1040 "out %[port], %[hi]" "\ 1041\ " 1042 "rcall bitTimeB" "\ 1043\ " 1044 "out %[port], %[hi]" "\ 1045\ " 1046 "rcall bitTimeB" "\ 1047\ " 1048 "out %[port], %[hi]" "\ 1049\ " 1050 "rcall bitTimeB" "\ 1051\ " 1052 "out %[port], %[hi]" "\ 1053\ " 1054 "rcall bitTimeB" "\ 1055\ " 1056 "out %[port], %[hi]" "\ 1057\ " 1058 "rcall bitTimeB" "\ 1059\ " 1060 "out %[port], %[hi]" "\ 1061\ " 1062 "rcall bitTimeB" "\ 1063\ " 1064 "out %[port] , %[hi]" "\ 1065\ " 1066 "rjmp .+0" "\ 1067\ " 1068 "ld %[byte] , %a[ptr]+" "\ 1069\ " 1070 "out %[port] , %[next]" "\ 1071\ " 1072 "mov %[next] , %[lo]" "\ 1073\ " 1074 "sbrc %[byte] , 7" "\ 1075\ " 1076 "mov %[next] , %[hi]" "\ 1077\ " 1078 "nop" "\ 1079\ " 1080 "out %[port] , %[lo]" "\ 1081\ " 1082 "sbiw %[count], 1" "\ 1083\ " 1084 "brne headB" "\ 1085\ " 1086 "rjmp doneB" "\ 1087\ " 1088 "bitTimeB:" "\ 1089\ " 1090 "out %[port], %[next]" "\ 1091\ " 1092 "mov %[next], %[lo]" "\ 1093\ " 1094 "rol %[byte]" "\ 1095\ " 1096 "sbrc %[byte], 7" "\ 1097\ " 1098 "mov %[next], %[hi]" "\ 1099\ " 1100 "nop" "\ 1101\ " 1102 "out %[port], %[lo]" "\ 1103\ " 1104 "ret" "\ 1105\ " 1106 "doneB:" "\ 1107" 1108 : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i) 1109 : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), 1110 [lo] "r" (lo)); 1111 1112 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 1113 } 1114 #endif 1115 #if defined(PORTC) || defined(PORTF) 1116 else 1117 #endif // defined(PORTC/F) 1118#endif // defined(PORTB) 1119 1120 // PORTC OUTPUT ---------------------------------------------------- 1121 1122#if defined(PORTC) 1123 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 1124 if(port == &PORTC) { 1125 #endif // defined(PORTD/B/F) 1126 1127 hi = PORTC | pinMask; 1128 lo = PORTC & ~pinMask; 1129 next = lo; 1130 if(b & 0x80) next = hi; 1131 1132 // Same as above, just set for PORTC & stripped of comments 1133 asm volatile( 1134 "headC:" "\ 1135\ " 1136 "out %[port], %[hi]" "\ 1137\ " 1138 "rcall bitTimeC" "\ 1139\ " 1140 "out %[port], %[hi]" "\ 1141\ " 1142 "rcall bitTimeC" "\ 1143\ " 1144 "out %[port], %[hi]" "\ 1145\ " 1146 "rcall bitTimeC" "\ 1147\ " 1148 "out %[port], %[hi]" "\ 1149\ " 1150 "rcall bitTimeC" "\ 1151\ " 1152 "out %[port], %[hi]" "\ 1153\ " 1154 "rcall bitTimeC" "\ 1155\ " 1156 "out %[port], %[hi]" "\ 1157\ " 1158 "rcall bitTimeC" "\ 1159\ " 1160 "out %[port], %[hi]" "\ 1161\ " 1162 "rcall bitTimeC" "\ 1163\ " 1164 "out %[port] , %[hi]" "\ 1165\ " 1166 "rjmp .+0" "\ 1167\ " 1168 "ld %[byte] , %a[ptr]+" "\ 1169\ " 1170 "out %[port] , %[next]" "\ 1171\ " 1172 "mov %[next] , %[lo]" "\ 1173\ " 1174 "sbrc %[byte] , 7" "\ 1175\ " 1176 "mov %[next] , %[hi]" "\ 1177\ " 1178 "nop" "\ 1179\ " 1180 "out %[port] , %[lo]" "\ 1181\ " 1182 "sbiw %[count], 1" "\ 1183\ " 1184 "brne headC" "\ 1185\ " 1186 "rjmp doneC" "\ 1187\ " 1188 "bitTimeC:" "\ 1189\ " 1190 "out %[port], %[next]" "\ 1191\ " 1192 "mov %[next], %[lo]" "\ 1193\ " 1194 "rol %[byte]" "\ 1195\ " 1196 "sbrc %[byte], 7" "\ 1197\ " 1198 "mov %[next], %[hi]" "\ 1199\ " 1200 "nop" "\ 1201\ " 1202 "out %[port], %[lo]" "\ 1203\ " 1204 "ret" "\ 1205\ " 1206 "doneC:" "\ 1207" 1208 : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i) 1209 : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi), 1210 [lo] "r" (lo)); 1211 1212 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 1213 } 1214 #endif // defined(PORTD/B/F) 1215 #if defined(PORTF) 1216 else 1217 #endif 1218#endif // defined(PORTC) 1219 1220 // PORTF OUTPUT ---------------------------------------------------- 1221 1222#if defined(PORTF) 1223 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 1224 if(port == &PORTF) { 1225 #endif // defined(PORTD/B/C) 1226 1227 hi = PORTF | pinMask; 1228 lo = PORTF & ~pinMask; 1229 next = lo; 1230 if(b & 0x80) next = hi; 1231 1232 // Same as above, just set for PORTF & stripped of comments 1233 asm volatile( 1234 "headF:" "\ 1235\ " 1236 "out %[port], %[hi]" "\ 1237\ " 1238 "rcall bitTimeC" "\ 1239\ " 1240 "out %[port], %[hi]" "\ 1241\ " 1242 "rcall bitTimeC" "\ 1243\ " 1244 "out %[port], %[hi]" "\ 1245\ " 1246 "rcall bitTimeC" "\ 1247\ " 1248 "out %[port], %[hi]" "\ 1249\ " 1250 "rcall bitTimeC" "\ 1251\ " 1252 "out %[port], %[hi]" "\ 1253\ " 1254 "rcall bitTimeC" "\ 1255\ " 1256 "out %[port], %[hi]" "\ 1257\ " 1258 "rcall bitTimeC" "\ 1259\ " 1260 "out %[port], %[hi]" "\ 1261\ " 1262 "rcall bitTimeC" "\ 1263\ " 1264 "out %[port] , %[hi]" "\ 1265\ " 1266 "rjmp .+0" "\ 1267\ " 1268 "ld %[byte] , %a[ptr]+" "\ 1269\ " 1270 "out %[port] , %[next]" "\ 1271\ " 1272 "mov %[next] , %[lo]" "\ 1273\ " 1274 "sbrc %[byte] , 7" "\ 1275\ " 1276 "mov %[next] , %[hi]" "\ 1277\ " 1278 "nop" "\ 1279\ " 1280 "out %[port] , %[lo]" "\ 1281\ " 1282 "sbiw %[count], 1" "\ 1283\ " 1284 "brne headF" "\ 1285\ " 1286 "rjmp doneC" "\ 1287\ " 1288 "bitTimeC:" "\ 1289\ " 1290 "out %[port], %[next]" "\ 1291\ " 1292 "mov %[next], %[lo]" "\ 1293\ " 1294 "rol %[byte]" "\ 1295\ " 1296 "sbrc %[byte], 7" "\ 1297\ " 1298 "mov %[next], %[hi]" "\ 1299\ " 1300 "nop" "\ 1301\ " 1302 "out %[port], %[lo]" "\ 1303\ " 1304 "ret" "\ 1305\ " 1306 "doneC:" "\ 1307" 1308 : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i) 1309 : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi), 1310 [lo] "r" (lo)); 1311 1312 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 1313 } 1314 #endif // defined(PORTD/B/C) 1315#endif // defined(PORTF) 1316 1317#ifdef NEO_KHZ400 1318 } else { // 400 KHz 1319 1320 // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL 1321 // ST instructions: ^ ^ ^ (T=0,6,15) 1322 1323 volatile uint8_t next, bit; 1324 1325 hi = *port | pinMask; 1326 lo = *port & ~pinMask; 1327 next = lo; 1328 bit = 8; 1329 1330 asm volatile( 1331 "head30:" "\ 1332\ " // Clk Pseudocode (T = 0) 1333 "st %a[port], %[hi]" "\ 1334\ " // 2 PORT = hi (T = 2) 1335 "sbrc %[byte] , 7" "\ 1336\ " // 1-2 if(b & 128) 1337 "mov %[next], %[hi]" "\ 1338\ " // 0-1 next = hi (T = 4) 1339 "rjmp .+0" "\ 1340\ " // 2 nop nop (T = 6) 1341 "st %a[port], %[next]" "\ 1342\ " // 2 PORT = next (T = 8) 1343 "rjmp .+0" "\ 1344\ " // 2 nop nop (T = 10) 1345 "rjmp .+0" "\ 1346\ " // 2 nop nop (T = 12) 1347 "rjmp .+0" "\ 1348\ " // 2 nop nop (T = 14) 1349 "nop" "\ 1350\ " // 1 nop (T = 15) 1351 "st %a[port], %[lo]" "\ 1352\ " // 2 PORT = lo (T = 17) 1353 "rjmp .+0" "\ 1354\ " // 2 nop nop (T = 19) 1355 "dec %[bit]" "\ 1356\ " // 1 bit-- (T = 20) 1357 "breq nextbyte30" "\ 1358\ " // 1-2 if(bit == 0) 1359 "rol %[byte]" "\ 1360\ " // 1 b <<= 1 (T = 22) 1361 "rjmp .+0" "\ 1362\ " // 2 nop nop (T = 24) 1363 "rjmp .+0" "\ 1364\ " // 2 nop nop (T = 26) 1365 "rjmp .+0" "\ 1366\ " // 2 nop nop (T = 28) 1367 "rjmp head30" "\ 1368\ " // 2 -> head30 (next bit out) 1369 "nextbyte30:" "\ 1370\ " // (T = 22) 1371 "nop" "\ 1372\ " // 1 nop (T = 23) 1373 "ldi %[bit] , 8" "\ 1374\ " // 1 bit = 8 (T = 24) 1375 "ld %[byte] , %a[ptr]+" "\ 1376\ " // 2 b = *ptr++ (T = 26) 1377 "sbiw %[count], 1" "\ 1378\ " // 2 i-- (T = 28) 1379 "brne head30" "\ 1380" // 1-2 if(i != 0) -> (next byte) 1381 : [port] "+e" (port), 1382 [byte] "+r" (b), 1383 [bit] "+r" (bit), 1384 [next] "+r" (next), 1385 [count] "+w" (i) 1386 : [hi] "r" (hi), 1387 [lo] "r" (lo), 1388 [ptr] "e" (ptr)); 1389 } 1390#endif // NEO_KHZ400 1391 1392// 16 MHz(ish) AVR -------------------------------------------------------- 1393#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) 1394 1395#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 1396 if(is800KHz) { 1397#endif 1398 1399 // WS2811 and WS2812 have different hi/lo duty cycles; this is 1400 // similar but NOT an exact copy of the prior 400-on-8 code. 1401 1402 // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL 1403 // ST instructions: ^ ^ ^ (T=0,5,13) 1404 1405 volatile uint8_t next, bit; 1406 1407 hi = *port | pinMask; 1408 lo = *port & ~pinMask; 1409 next = lo; 1410 bit = 8; 1411 1412 asm volatile( 1413 "head20:" "\ 1414\ " // Clk Pseudocode (T = 0) 1415 "st %a[port], %[hi]" "\ 1416\ " // 2 PORT = hi (T = 2) 1417 "sbrc %[byte], 7" "\ 1418\ " // 1-2 if(b & 128) 1419 "mov %[next], %[hi]" "\ 1420\ " // 0-1 next = hi (T = 4) 1421 "dec %[bit]" "\ 1422\ " // 1 bit-- (T = 5) 1423 "st %a[port], %[next]" "\ 1424\ " // 2 PORT = next (T = 7) 1425 "mov %[next] , %[lo]" "\ 1426\ " // 1 next = lo (T = 8) 1427 "breq nextbyte20" "\ 1428\ " // 1-2 if(bit == 0) (from dec above) 1429 "rol %[byte]" "\ 1430\ " // 1 b <<= 1 (T = 10) 1431 "rjmp .+0" "\ 1432\ " // 2 nop nop (T = 12) 1433 "nop" "\ 1434\ " // 1 nop (T = 13) 1435 "st %a[port], %[lo]" "\ 1436\ " // 2 PORT = lo (T = 15) 1437 "nop" "\ 1438\ " // 1 nop (T = 16) 1439 "rjmp .+0" "\ 1440\ " // 2 nop nop (T = 18) 1441 "rjmp head20" "\ 1442\ " // 2 -> head20 (next bit out) 1443 "nextbyte20:" "\ 1444\ " // (T = 10) 1445 "ldi %[bit] , 8" "\ 1446\ " // 1 bit = 8 (T = 11) 1447 "ld %[byte] , %a[ptr]+" "\ 1448\ " // 2 b = *ptr++ (T = 13) 1449 "st %a[port], %[lo]" "\ 1450\ " // 2 PORT = lo (T = 15) 1451 "nop" "\ 1452\ " // 1 nop (T = 16) 1453 "sbiw %[count], 1" "\ 1454\ " // 2 i-- (T = 18) 1455 "brne head20" "\ 1456" // 2 if(i != 0) -> (next byte) 1457 : [port] "+e" (port), 1458 [byte] "+r" (b), 1459 [bit] "+r" (bit), 1460 [next] "+r" (next), 1461 [count] "+w" (i) 1462 : [ptr] "e" (ptr), 1463 [hi] "r" (hi), 1464 [lo] "r" (lo)); 1465 1466#ifdef NEO_KHZ400 1467 } else { // 400 KHz 1468 1469 // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version. 1470 1471 // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL 1472 // ST instructions: ^ ^ ^ (T=0,8,20) 1473 1474 volatile uint8_t next, bit; 1475 1476 hi = *port | pinMask; 1477 lo = *port & ~pinMask; 1478 next = lo; 1479 bit = 8; 1480 1481 asm volatile( 1482 "head40:" "\ 1483\ " // Clk Pseudocode (T = 0) 1484 "st %a[port], %[hi]" "\ 1485\ " // 2 PORT = hi (T = 2) 1486 "sbrc %[byte] , 7" "\ 1487\ " // 1-2 if(b & 128) 1488 "mov %[next] , %[hi]" "\ 1489\ " // 0-1 next = hi (T = 4) 1490 "rjmp .+0" "\ 1491\ " // 2 nop nop (T = 6) 1492 "rjmp .+0" "\ 1493\ " // 2 nop nop (T = 8) 1494 "st %a[port], %[next]" "\ 1495\ " // 2 PORT = next (T = 10) 1496 "rjmp .+0" "\ 1497\ " // 2 nop nop (T = 12) 1498 "rjmp .+0" "\ 1499\ " // 2 nop nop (T = 14) 1500 "rjmp .+0" "\ 1501\ " // 2 nop nop (T = 16) 1502 "rjmp .+0" "\ 1503\ " // 2 nop nop (T = 18) 1504 "rjmp .+0" "\ 1505\ " // 2 nop nop (T = 20) 1506 "st %a[port], %[lo]" "\ 1507\ " // 2 PORT = lo (T = 22) 1508 "nop" "\ 1509\ " // 1 nop (T = 23) 1510 "mov %[next] , %[lo]" "\ 1511\ " // 1 next = lo (T = 24) 1512 "dec %[bit]" "\ 1513\ " // 1 bit-- (T = 25) 1514 "breq nextbyte40" "\ 1515\ " // 1-2 if(bit == 0) 1516 "rol %[byte]" "\ 1517\ " // 1 b <<= 1 (T = 27) 1518 "nop" "\ 1519\ " // 1 nop (T = 28) 1520 "rjmp .+0" "\ 1521\ " // 2 nop nop (T = 30) 1522 "rjmp .+0" "\ 1523\ " // 2 nop nop (T = 32) 1524 "rjmp .+0" "\ 1525\ " // 2 nop nop (T = 34) 1526 "rjmp .+0" "\ 1527\ " // 2 nop nop (T = 36) 1528 "rjmp .+0" "\ 1529\ " // 2 nop nop (T = 38) 1530 "rjmp head40" "\ 1531\ " // 2 -> head40 (next bit out) 1532 "nextbyte40:" "\ 1533\ " // (T = 27) 1534 "ldi %[bit] , 8" "\ 1535\ " // 1 bit = 8 (T = 28) 1536 "ld %[byte] , %a[ptr]+" "\ 1537\ " // 2 b = *ptr++ (T = 30) 1538 "rjmp .+0" "\ 1539\ " // 2 nop nop (T = 32) 1540 "st %a[port], %[lo]" "\ 1541\ " // 2 PORT = lo (T = 34) 1542 "rjmp .+0" "\ 1543\ " // 2 nop nop (T = 36) 1544 "sbiw %[count], 1" "\ 1545\ " // 2 i-- (T = 38) 1546 "brne head40" "\ 1547" // 1-2 if(i != 0) -> (next byte) 1548 : [port] "+e" (port), 1549 [byte] "+r" (b), 1550 [bit] "+r" (bit), 1551 [next] "+r" (next), 1552 [count] "+w" (i) 1553 : [ptr] "e" (ptr), 1554 [hi] "r" (hi), 1555 [lo] "r" (lo)); 1556 } 1557#endif // NEO_KHZ400 1558 1559#else 1560 #error "CPU SPEED NOT SUPPORTED" 1561#endif // end F_CPU ifdefs on __AVR__ 1562 1563// END AVR ---------------------------------------------------------------- 1564 1565 1566#elif defined(__arm__) 1567 1568// ARM MCUs -- Teensy 3.0, 3.1, LC, Arduino Due --------------------------- 1569 1570#if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6 1571#define CYCLES_800_T0H (F_CPU / 4000000) 1572#define CYCLES_800_T1H (F_CPU / 1250000) 1573#define CYCLES_800 (F_CPU / 800000) 1574#define CYCLES_400_T0H (F_CPU / 2000000) 1575#define CYCLES_400_T1H (F_CPU / 833333) 1576#define CYCLES_400 (F_CPU / 400000) 1577 1578 uint8_t *p = pixels, 1579 *end = p + numBytes, pix, mask; 1580 volatile uint8_t *set = portSetRegister(pin), 1581 *clr = portClearRegister(pin); 1582 uint32_t cyc; 1583 1584 ARM_DEMCR |= ARM_DEMCR_TRCENA; 1585 ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; 1586 1587#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 1588 if(is800KHz) { 1589#endif 1590 cyc = ARM_DWT_CYCCNT + CYCLES_800; 1591 while(p < end) { 1592 pix = *p++; 1593 for(mask = 0x80; mask; mask >>= 1) { 1594 while(ARM_DWT_CYCCNT - cyc < CYCLES_800); 1595 cyc = ARM_DWT_CYCCNT; 1596 *set = 1; 1597 if(pix & mask) { 1598 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H); 1599 } else { 1600 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H); 1601 } 1602 *clr = 1; 1603 } 1604 } 1605 while(ARM_DWT_CYCCNT - cyc < CYCLES_800); 1606#ifdef NEO_KHZ400 1607 } else { // 400 kHz bitstream 1608 cyc = ARM_DWT_CYCCNT + CYCLES_400; 1609 while(p < end) { 1610 pix = *p++; 1611 for(mask = 0x80; mask; mask >>= 1) { 1612 while(ARM_DWT_CYCCNT - cyc < CYCLES_400); 1613 cyc = ARM_DWT_CYCCNT; 1614 *set = 1; 1615 if(pix & mask) { 1616 while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H); 1617 } else { 1618 while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H); 1619 } 1620 *clr = 1; 1621 } 1622 } 1623 while(ARM_DWT_CYCCNT - cyc < CYCLES_400); 1624 } 1625#endif // NEO_KHZ400 1626 1627#elif defined(TEENSYDUINO) && defined(__MKL26Z64__) // Teensy-LC 1628 1629#if F_CPU == 48000000 1630 uint8_t *p = pixels, 1631 pix, count, dly, 1632 bitmask = digitalPinToBitMask(pin); 1633 volatile uint8_t *reg = portSetRegister(pin); 1634 uint32_t num = numBytes; 1635 asm volatile( 1636 "L%=_begin:" "\ 1637\ " 1638 "ldrb %[pix], [%[p], #0]" "\ 1639\ " 1640 "lsl %[pix], #24" "\ 1641\ " 1642 "movs %[count], #7" "\ 1643\ " 1644 "L%=_loop:" "\ 1645\ " 1646 "lsl %[pix], #1" "\ 1647\ " 1648 "bcs L%=_loop_one" "\ 1649\ " 1650 "L%=_loop_zero:" 1651 "strb %[bitmask], [%[reg], #0]" "\ 1652\ " 1653 "movs %[dly], #4" "\ 1654\ " 1655 "L%=_loop_delay_T0H:" "\ 1656\ " 1657 "sub %[dly], #1" "\ 1658\ " 1659 "bne L%=_loop_delay_T0H" "\ 1660\ " 1661 "strb %[bitmask], [%[reg], #4]" "\ 1662\ " 1663 "movs %[dly], #13" "\ 1664\ " 1665 "L%=_loop_delay_T0L:" "\ 1666\ " 1667 "sub %[dly], #1" "\ 1668\ " 1669 "bne L%=_loop_delay_T0L" "\ 1670\ " 1671 "b L%=_next" "\ 1672\ " 1673 "L%=_loop_one:" 1674 "strb %[bitmask], [%[reg], #0]" "\ 1675\ " 1676 "movs %[dly], #13" "\ 1677\ " 1678 "L%=_loop_delay_T1H:" "\ 1679\ " 1680 "sub %[dly], #1" "\ 1681\ " 1682 "bne L%=_loop_delay_T1H" "\ 1683\ " 1684 "strb %[bitmask], [%[reg], #4]" "\ 1685\ " 1686 "movs %[dly], #4" "\ 1687\ " 1688 "L%=_loop_delay_T1L:" "\ 1689\ " 1690 "sub %[dly], #1" "\ 1691\ " 1692 "bne L%=_loop_delay_T1L" "\ 1693\ " 1694 "nop" "\ 1695\ " 1696 "L%=_next:" "\ 1697\ " 1698 "sub %[count], #1" "\ 1699\ " 1700 "bne L%=_loop" "\ 1701\ " 1702 "lsl %[pix], #1" "\ 1703\ " 1704 "bcs L%=_last_one" "\ 1705\ " 1706 "L%=_last_zero:" 1707 "strb %[bitmask], [%[reg], #0]" "\ 1708\ " 1709 "movs %[dly], #4" "\ 1710\ " 1711 "L%=_last_delay_T0H:" "\ 1712\ " 1713 "sub %[dly], #1" "\ 1714\ " 1715 "bne L%=_last_delay_T0H" "\ 1716\ " 1717 "strb %[bitmask], [%[reg], #4]" "\ 1718\ " 1719 "movs %[dly], #10" "\ 1720\ " 1721 "L%=_last_delay_T0L:" "\ 1722\ " 1723 "sub %[dly], #1" "\ 1724\ " 1725 "bne L%=_last_delay_T0L" "\ 1726\ " 1727 "b L%=_repeat" "\ 1728\ " 1729 "L%=_last_one:" 1730 "strb %[bitmask], [%[reg], #0]" "\ 1731\ " 1732 "movs %[dly], #13" "\ 1733\ " 1734 "L%=_last_delay_T1H:" "\ 1735\ " 1736 "sub %[dly], #1" "\ 1737\ " 1738 "bne L%=_last_delay_T1H" "\ 1739\ " 1740 "strb %[bitmask], [%[reg], #4]" "\ 1741\ " 1742 "movs %[dly], #1" "\ 1743\ " 1744 "L%=_last_delay_T1L:" "\ 1745\ " 1746 "sub %[dly], #1" "\ 1747\ " 1748 "bne L%=_last_delay_T1L" "\ 1749\ " 1750 "nop" "\ 1751\ " 1752 "L%=_repeat:" "\ 1753\ " 1754 "add %[p], #1" "\ 1755\ " 1756 "sub %[num], #1" "\ 1757\ " 1758 "bne L%=_begin" "\ 1759\ " 1760 "L%=_done:" "\ 1761\ " 1762 : [p] "+r" (p), 1763 [pix] "=&r" (pix), 1764 [count] "=&r" (count), 1765 [dly] "=&r" (dly), 1766 [num] "+r" (num) 1767 : [bitmask] "r" (bitmask), 1768 [reg] "r" (reg) 1769 ); 1770#else 1771#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz" 1772#endif // F_CPU == 48000000 1773 1774// Begin of support for NRF52832 based boards ------------------------- 1775 1776#elif defined(NRF52) 1777// [[[Begin of the Neopixel NRF52 EasyDMA implementation 1778// by the Hackerspace San Salvador]]] 1779// This technique uses the PWM peripheral on the NRF52. The PWM uses the 1780// EasyDMA feature included on the chip. This technique loads the duty 1781// cycle configuration for each cycle when the PWM is enabled. For this 1782// to work we need to store a 16 bit configuration for each bit of the 1783// RGB(W) values in the pixel buffer. 1784// Comparator values for the PWM were hand picked and are guaranteed to 1785// be 100% organic to preserve freshness and high accuracy. Current 1786// parameters are: 1787// * PWM Clock: 16Mhz 1788// * Minimum step time: 62.5ns 1789// * Time for zero in high (T0H): 0.31ms 1790// * Time for one in high (T1H): 0.75ms 1791// * Cycle time: 1.25us 1792// * Frequency: 800Khz 1793// For 400Khz we just double the calculated times. 1794// ---------- BEGIN Constants for the EasyDMA implementation ----------- 1795// The PWM starts the duty cycle in LOW. To start with HIGH we 1796// need to set the 15th bit on each register. 1797 1798// WS2812 (rev A) timing is 0.35 and 0.7us 1799//#define MAGIC_T0H 5UL | (0x8000) // 0.3125us 1800//#define MAGIC_T1H 12UL | (0x8000) // 0.75us 1801 1802// WS2812B (rev B) timing is 0.4 and 0.8 us 1803#define MAGIC_T0H 6UL | (0x8000) // 0.375us 1804#define MAGIC_T1H 13UL | (0x8000) // 0.8125us 1805 1806// WS2811 (400 khz) timing is 0.5 and 1.2 1807#define MAGIC_T0H_400KHz 8UL | (0x8000) // 0.5us 1808#define MAGIC_T1H_400KHz 19UL | (0x8000) // 1.1875us 1809 1810// For 400Khz, we double value of CTOPVAL 1811#define CTOPVAL 20UL // 1.25us 1812#define CTOPVAL_400KHz 40UL // 2.5us 1813 1814// ---------- END Constants for the EasyDMA implementation ------------- 1815// 1816// If there is no device available an alternative cycle-counter 1817// implementation is tried. 1818// The nRF52832 runs with a fixed clock of 64Mhz. The alternative 1819// implementation is the same as the one used for the Teensy 3.0/1/2 but 1820// with the Nordic SDK HAL & registers syntax. 1821// The number of cycles was hand picked and is guaranteed to be 100% 1822// organic to preserve freshness and high accuracy. 1823// ---------- BEGIN Constants for cycle counter implementation --------- 1824#define CYCLES_800_T0H 18 // ~0.36 uS 1825#define CYCLES_800_T1H 41 // ~0.76 uS 1826#define CYCLES_800 71 // ~1.25 uS 1827 1828#define CYCLES_400_T0H 26 // ~0.50 uS 1829#define CYCLES_400_T1H 70 // ~1.26 uS 1830#define CYCLES_400 156 // ~2.50 uS 1831// ---------- END of Constants for cycle counter implementation -------- 1832 1833 // To support both the SoftDevice + Neopixels we use the EasyDMA 1834 // feature from the NRF25. However this technique implies to 1835 // generate a pattern and store it on the memory. The actual 1836 // memory used in bytes corresponds to the following formula: 1837 // totalMem = numBytes*8*2+(2*2) 1838 // The two additional bytes at the end are needed to reset the 1839 // sequence. 1840 // 1841 // If there is not enough memory, we will fall back to cycle counter 1842 // using DWT 1843 uint32_t pattern_size = numBytes*8*sizeof(uint16_t)+2*sizeof(uint16_t); 1844 uint16_t* pixels_pattern = NULL; 1845 1846 NRF_PWM_Type* pwm = NULL; 1847 1848 // Try to find a free PWM device, which is not enabled 1849 // and has no connected pins 1850 NRF_PWM_Type* PWM[3] = {NRF_PWM0, NRF_PWM1, NRF_PWM2}; 1851 for(int device = 0; device<3; device++) { 1852 if( (PWM[device]->ENABLE == 0) && 1853 (PWM[device]->PSEL.OUT[0] & PWM_PSEL_OUT_CONNECT_Msk) && 1854 (PWM[device]->PSEL.OUT[1] & PWM_PSEL_OUT_CONNECT_Msk) && 1855 (PWM[device]->PSEL.OUT[2] & PWM_PSEL_OUT_CONNECT_Msk) && 1856 (PWM[device]->PSEL.OUT[3] & PWM_PSEL_OUT_CONNECT_Msk) 1857 ) { 1858 pwm = PWM[device]; 1859 break; 1860 } 1861 } 1862 1863 // only malloc if there is PWM device available 1864 if ( pwm != NULL ) { 1865 #ifdef ARDUINO_FEATHER52 // use thread-safe malloc 1866 pixels_pattern = (uint16_t *) rtos_malloc(pattern_size); 1867 #else 1868 pixels_pattern = (uint16_t *) malloc(pattern_size); 1869 #endif 1870 } 1871 1872 // Use the identified device to choose the implementation 1873 // If a PWM device is available use DMA 1874 if( (pixels_pattern != NULL) && (pwm != NULL) ) { 1875 uint16_t pos = 0; // bit position 1876 1877 for(uint16_t n=0; n<numBytes; n++) { 1878 uint8_t pix = pixels[n]; 1879 1880 for(uint8_t mask=0x80, i=0; mask>0; mask >>= 1, i++) { 1881 #ifdef NEO_KHZ400 1882 if( !is800KHz ) { 1883 pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H_400KHz : MAGIC_T0H_400KHz; 1884 }else 1885 #endif 1886 { 1887 pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H; 1888 } 1889 1890 pos++; 1891 } 1892 } 1893 1894 // Zero padding to indicate the end of que sequence 1895 pixels_pattern[++pos] = 0 | (0x8000); // Seq end 1896 pixels_pattern[++pos] = 0 | (0x8000); // Seq end 1897 1898 // Set the wave mode to count UP 1899 pwm->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos); 1900 1901 // Set the PWM to use the 16MHz clock 1902 pwm->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos); 1903 1904 // Setting of the maximum count 1905 // but keeping it on 16Mhz allows for more granularity just 1906 // in case someone wants to do more fine-tuning of the timing. 1907#ifdef NEO_KHZ400 1908 if( !is800KHz ) { 1909 pwm->COUNTERTOP = (CTOPVAL_400KHz << PWM_COUNTERTOP_COUNTERTOP_Pos); 1910 }else 1911#endif 1912 { 1913 pwm->COUNTERTOP = (CTOPVAL << PWM_COUNTERTOP_COUNTERTOP_Pos); 1914 } 1915 1916 // Disable loops, we want the sequence to repeat only once 1917 pwm->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos); 1918 1919 // On the "Common" setting the PWM uses the same pattern for the 1920 // for supported sequences. The pattern is stored on half-word 1921 // of 16bits 1922 pwm->DECODER = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | 1923 (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos); 1924 1925 // Pointer to the memory storing the patter 1926 pwm->SEQ[0].PTR = (uint32_t)(pixels_pattern) << PWM_SEQ_PTR_PTR_Pos; 1927 1928 // Calculation of the number of steps loaded from memory. 1929 pwm->SEQ[0].CNT = (pattern_size/sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos; 1930 1931 // The following settings are ignored with the current config. 1932 pwm->SEQ[0].REFRESH = 0; 1933 pwm->SEQ[0].ENDDELAY = 0; 1934 1935 // The Neopixel implementation is a blocking algorithm. DMA 1936 // allows for non-blocking operation. To "simulate" a blocking 1937 // operation we enable the interruption for the end of sequence 1938 // and block the execution thread until the event flag is set by 1939 // the peripheral. 1940// pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos); 1941 1942 // PSEL must be configured before enabling PWM 1943 pwm->PSEL.OUT[0] = g_ADigitalPinMap[pin]; 1944 1945 // Enable the PWM 1946 pwm->ENABLE = 1; 1947 1948 // After all of this and many hours of reading the documentation 1949 // we are ready to start the sequence... 1950 pwm->EVENTS_SEQEND[0] = 0; 1951 pwm->TASKS_SEQSTART[0] = 1; 1952 1953 // But we have to wait for the flag to be set. 1954 while(!pwm->EVENTS_SEQEND[0]) 1955 { 1956 #ifdef ARDUINO_FEATHER52 1957 yield(); 1958 #endif 1959 } 1960 1961 // Before leave we clear the flag for the event. 1962 pwm->EVENTS_SEQEND[0] = 0; 1963 1964 // We need to disable the device and disconnect 1965 // all the outputs before leave or the device will not 1966 // be selected on the next call. 1967 // TODO: Check if disabling the device causes performance issues. 1968 pwm->ENABLE = 0; 1969 1970 pwm->PSEL.OUT[0] = 0xFFFFFFFFUL; 1971 1972 #ifdef ARDUINO_FEATHER52 // use thread-safe free 1973 rtos_free(pixels_pattern); 1974 #else 1975 free(pixels_pattern); 1976 #endif 1977 }// End of DMA implementation 1978 // --------------------------------------------------------------------- 1979 else{ 1980 // Fall back to DWT 1981 #ifdef ARDUINO_FEATHER52 1982 // Bluefruit Feather 52 uses freeRTOS 1983 // Critical Section is used since it does not block SoftDevice execution 1984 taskENTER_CRITICAL(); 1985 #elif defined(NRF52_DISABLE_INT) 1986 // If you are using the Bluetooth SoftDevice we advise you to not disable 1987 // the interrupts. Disabling the interrupts even for short periods of time 1988 // causes the SoftDevice to stop working. 1989 // Disable the interrupts only in cases where you need high performance for 1990 // the LEDs and if you are not using the EasyDMA feature. 1991 __disable_irq(); 1992 #endif 1993 1994 uint32_t pinMask = 1UL << g_ADigitalPinMap[pin]; 1995 1996 uint32_t CYCLES_X00 = CYCLES_800; 1997 uint32_t CYCLES_X00_T1H = CYCLES_800_T1H; 1998 uint32_t CYCLES_X00_T0H = CYCLES_800_T0H; 1999 2000#ifdef NEO_KHZ400 2001 if( !is800KHz ) 2002 { 2003 CYCLES_X00 = CYCLES_400; 2004 CYCLES_X00_T1H = CYCLES_400_T1H; 2005 CYCLES_X00_T0H = CYCLES_400_T0H; 2006 } 2007#endif 2008 2009 // Enable DWT in debug core 2010 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; 2011 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; 2012 2013 // Tries to re-send the frame if is interrupted by the SoftDevice. 2014 while(1) { 2015 uint8_t *p = pixels; 2016 2017 uint32_t cycStart = DWT->CYCCNT; 2018 uint32_t cyc = 0; 2019 2020 for(uint16_t n=0; n<numBytes; n++) { 2021 uint8_t pix = *p++; 2022 2023 for(uint8_t mask = 0x80; mask; mask >>= 1) { 2024 while(DWT->CYCCNT - cyc < CYCLES_X00); 2025 cyc = DWT->CYCCNT; 2026 2027 NRF_GPIO->OUTSET |= pinMask; 2028 2029 if(pix & mask) { 2030 while(DWT->CYCCNT - cyc < CYCLES_X00_T1H); 2031 } else { 2032 while(DWT->CYCCNT - cyc < CYCLES_X00_T0H); 2033 } 2034 2035 NRF_GPIO->OUTCLR |= pinMask; 2036 } 2037 } 2038 while(DWT->CYCCNT - cyc < CYCLES_X00); 2039 2040 2041 // If total time longer than 25%, resend the whole data. 2042 // Since we are likely to be interrupted by SoftDevice 2043 if ( (DWT->CYCCNT - cycStart) < ( 8*numBytes*((CYCLES_X00*5)/4) ) ) { 2044 break; 2045 } 2046 2047 // re-send need 300us delay 2048 delayMicroseconds(300); 2049 } 2050 2051 // Enable interrupts again 2052 #ifdef ARDUINO_FEATHER52 2053 taskEXIT_CRITICAL(); 2054 #elif defined(NRF52_DISABLE_INT) 2055 __enable_irq(); 2056 #endif 2057 } 2058// END of NRF52 implementation 2059 2060#elif defined (__SAMD21E17A__) || defined(__SAMD21G18A__) || defined(__SAMD21E18A__) || defined(__SAMD21J18A__) // Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo and others 2061 // Tried this with a timer/counter, couldn't quite get adequate 2062 // resolution. So yay, you get a load of goofball NOPs... 2063 2064 uint8_t *ptr, *end, p, bitMask, portNum; 2065 uint32_t pinMask; 2066 2067 portNum = g_APinDescription[pin].ulPort; 2068 pinMask = 1ul << g_APinDescription[pin].ulPin; 2069 ptr = pixels; 2070 end = ptr + numBytes; 2071 p = *ptr++; 2072 bitMask = 0x80; 2073 2074 volatile uint32_t *set = &(PORT->Group[portNum].OUTSET.reg), 2075 *clr = &(PORT->Group[portNum].OUTCLR.reg); 2076 2077#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 2078 if(is800KHz) { 2079#endif 2080 for(;;) { 2081 *set = pinMask; 2082 asm("nop; nop; nop; nop; nop; nop; nop; nop;"); 2083 if(p & bitMask) { 2084 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2085 "nop; nop; nop; nop; nop; nop; nop; nop;" 2086 "nop; nop; nop; nop;"); 2087 *clr = pinMask; 2088 } else { 2089 *clr = pinMask; 2090 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2091 "nop; nop; nop; nop; nop; nop; nop; nop;" 2092 "nop; nop; nop; nop;"); 2093 } 2094 if(bitMask >>= 1) { 2095 asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;"); 2096 } else { 2097 if(ptr >= end) break; 2098 p = *ptr++; 2099 bitMask = 0x80; 2100 } 2101 } 2102#ifdef NEO_KHZ400 2103 } else { // 400 KHz bitstream 2104 for(;;) { 2105 *set = pinMask; 2106 asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); 2107 if(p & bitMask) { 2108 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2109 "nop; nop; nop; nop; nop; nop; nop; nop;" 2110 "nop; nop; nop; nop; nop; nop; nop; nop;" 2111 "nop; nop; nop;"); 2112 *clr = pinMask; 2113 } else { 2114 *clr = pinMask; 2115 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2116 "nop; nop; nop; nop; nop; nop; nop; nop;" 2117 "nop; nop; nop; nop; nop; nop; nop; nop;" 2118 "nop; nop; nop;"); 2119 } 2120 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2121 "nop; nop; nop; nop; nop; nop; nop; nop;" 2122 "nop; nop; nop; nop; nop; nop; nop; nop;" 2123 "nop; nop; nop; nop; nop; nop; nop; nop;"); 2124 if(bitMask >>= 1) { 2125 asm("nop; nop; nop; nop; nop; nop; nop;"); 2126 } else { 2127 if(ptr >= end) break; 2128 p = *ptr++; 2129 bitMask = 0x80; 2130 } 2131 } 2132 } 2133#endif 2134 2135#elif defined (__SAMD51__) // M4 @ 120mhz 2136 // Tried this with a timer/counter, couldn't quite get adequate 2137 // resolution. So yay, you get a load of goofball NOPs... 2138 2139 uint8_t *ptr, *end, p, bitMask, portNum; 2140 uint32_t pinMask; 2141 2142 portNum = g_APinDescription[pin].ulPort; 2143 pinMask = 1ul << g_APinDescription[pin].ulPin; 2144 ptr = pixels; 2145 end = ptr + numBytes; 2146 p = *ptr++; 2147 bitMask = 0x80; 2148 2149 volatile uint32_t *set = &(PORT->Group[portNum].OUTSET.reg), 2150 *clr = &(PORT->Group[portNum].OUTCLR.reg); 2151 2152#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 2153 if(is800KHz) { 2154#endif 2155 for(;;) { 2156 if(p & bitMask) { // ONE 2157 // High 800ns 2158 *set = pinMask; 2159 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2160 "nop; nop; nop; nop; nop; nop; nop; nop;" 2161 "nop; nop; nop; nop; nop; nop; nop; nop;" 2162 "nop; nop; nop; nop; nop; nop; nop; nop;" 2163 "nop; nop; nop; nop; nop; nop; nop; nop;" 2164 "nop; nop; nop; nop; nop; nop; nop; nop;" 2165 "nop; nop; nop; nop; nop; nop; nop; nop;" 2166 "nop; nop; nop; nop; nop; nop; nop; nop;" 2167 "nop; nop; nop; nop; nop; nop; nop; nop;" 2168 "nop; nop; nop; nop; nop; nop; nop; nop;"); 2169 // Low 450ns 2170 *clr = pinMask; 2171 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2172 "nop; nop; nop; nop; nop; nop; nop; nop;" 2173 "nop; nop; nop; nop; nop; nop; nop; nop;" 2174 "nop; nop; nop; nop; nop; nop; nop; nop;" 2175 "nop;"); 2176 } else { // ZERO 2177 // High 400ns 2178 *set = pinMask; 2179 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2180 "nop; nop; nop; nop; nop; nop; nop; nop;" 2181 "nop; nop; nop; nop; nop; nop; nop; nop;" 2182 "nop; nop; nop; nop; nop; nop; nop; nop;" 2183 "nop;"); 2184 // Low 850ns 2185 *clr = pinMask; 2186 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2187 "nop; nop; nop; nop; nop; nop; nop; nop;" 2188 "nop; nop; nop; nop; nop; nop; nop; nop;" 2189 "nop; nop; nop; nop; nop; nop; nop; nop;" 2190 "nop; nop; nop; nop; nop; nop; nop; nop;" 2191 "nop; nop; nop; nop; nop; nop; nop; nop;" 2192 "nop; nop; nop; nop; nop; nop; nop; nop;" 2193 "nop; nop; nop; nop; nop; nop; nop; nop;" 2194 "nop; nop; nop; nop; nop; nop; nop; nop;" 2195 "nop; nop; nop; nop; nop; nop; nop; nop;"); 2196 } 2197 if(bitMask >>= 1) { 2198 // Move on to the next pixel 2199 asm("nop;"); 2200 } else { 2201 if(ptr >= end) break; 2202 p = *ptr++; 2203 bitMask = 0x80; 2204 } 2205 } 2206#ifdef NEO_KHZ400 2207 } else { // 400 KHz bitstream 2208 // ToDo! 2209 } 2210#endif 2211 2212#elif defined (ARDUINO_STM32_FEATHER) // FEATHER WICED (120MHz) 2213 2214 // Tried this with a timer/counter, couldn't quite get adequate 2215 // resolution. So yay, you get a load of goofball NOPs... 2216 2217 uint8_t *ptr, *end, p, bitMask; 2218 uint32_t pinMask; 2219 2220 pinMask = BIT(PIN_MAP[pin].gpio_bit); 2221 ptr = pixels; 2222 end = ptr + numBytes; 2223 p = *ptr++; 2224 bitMask = 0x80; 2225 2226 volatile uint16_t *set = &(PIN_MAP[pin].gpio_device->regs->BSRRL); 2227 volatile uint16_t *clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH); 2228 2229#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 2230 if(is800KHz) { 2231#endif 2232 for(;;) { 2233 if(p & bitMask) { // ONE 2234 // High 800ns 2235 *set = pinMask; 2236 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2237 "nop; nop; nop; nop; nop; nop; nop; nop;" 2238 "nop; nop; nop; nop; nop; nop; nop; nop;" 2239 "nop; nop; nop; nop; nop; nop; nop; nop;" 2240 "nop; nop; nop; nop; nop; nop; nop; nop;" 2241 "nop; nop; nop; nop; nop; nop; nop; nop;" 2242 "nop; nop; nop; nop; nop; nop; nop; nop;" 2243 "nop; nop; nop; nop; nop; nop; nop; nop;" 2244 "nop; nop; nop; nop; nop; nop; nop; nop;" 2245 "nop; nop; nop; nop; nop; nop; nop; nop;" 2246 "nop; nop; nop; nop; nop; nop; nop; nop;" 2247 "nop; nop; nop; nop; nop; nop;"); 2248 // Low 450ns 2249 *clr = pinMask; 2250 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2251 "nop; nop; nop; nop; nop; nop; nop; nop;" 2252 "nop; nop; nop; nop; nop; nop; nop; nop;" 2253 "nop; nop; nop; nop; nop; nop; nop; nop;" 2254 "nop; nop; nop; nop; nop; nop;"); 2255 } else { // ZERO 2256 // High 400ns 2257 *set = pinMask; 2258 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2259 "nop; nop; nop; nop; nop; nop; nop; nop;" 2260 "nop; nop; nop; nop; nop; nop; nop; nop;" 2261 "nop; nop; nop; nop; nop; nop; nop; nop;" 2262 "nop; nop; nop; nop; nop; nop; nop; nop;" 2263 "nop;"); 2264 // Low 850ns 2265 *clr = pinMask; 2266 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2267 "nop; nop; nop; nop; nop; nop; nop; nop;" 2268 "nop; nop; nop; nop; nop; nop; nop; nop;" 2269 "nop; nop; nop; nop; nop; nop; nop; nop;" 2270 "nop; nop; nop; nop; nop; nop; nop; nop;" 2271 "nop; nop; nop; nop; nop; nop; nop; nop;" 2272 "nop; nop; nop; nop; nop; nop; nop; nop;" 2273 "nop; nop; nop; nop; nop; nop; nop; nop;" 2274 "nop; nop; nop; nop; nop; nop; nop; nop;" 2275 "nop; nop; nop; nop; nop; nop; nop; nop;" 2276 "nop; nop; nop; nop; nop; nop; nop; nop;" 2277 "nop; nop; nop; nop;"); 2278 } 2279 if(bitMask >>= 1) { 2280 // Move on to the next pixel 2281 asm("nop;"); 2282 } else { 2283 if(ptr >= end) break; 2284 p = *ptr++; 2285 bitMask = 0x80; 2286 } 2287 } 2288#ifdef NEO_KHZ400 2289 } else { // 400 KHz bitstream 2290 // ToDo! 2291 } 2292#endif 2293 2294#else // Other ARM architecture -- Presumed Arduino Due 2295 2296 #define SCALE VARIANT_MCK / 2UL / 1000000UL 2297 #define INST (2UL * F_CPU / VARIANT_MCK) 2298 #define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST)) 2299 #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST)) 2300 #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST)) 2301 #define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST)) 2302 #define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST)) 2303 #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST)) 2304 2305 int pinMask, time0, time1, period, t; 2306 Pio *port; 2307 volatile WoReg *portSet, *portClear, *timeValue, *timeReset; 2308 uint8_t *p, *end, pix, mask; 2309 2310 pmc_set_writeprotect(false); 2311 pmc_enable_periph_clk((uint32_t)TC3_IRQn); 2312 TC_Configure(TC1, 0, 2313 TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1); 2314 TC_Start(TC1, 0); 2315 2316 pinMask = g_APinDescription[pin].ulPin; // Don't 'optimize' these into 2317 port = g_APinDescription[pin].pPort; // declarations above. Want to 2318 portSet = &(port->PIO_SODR); // burn a few cycles after 2319 portClear = &(port->PIO_CODR); // starting timer to minimize 2320 timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'. 2321 timeReset = &(TC1->TC_CHANNEL[0].TC_CCR); 2322 p = pixels; 2323 end = p + numBytes; 2324 pix = *p++; 2325 mask = 0x80; 2326 2327#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 2328 if(is800KHz) { 2329#endif 2330 time0 = TIME_800_0; 2331 time1 = TIME_800_1; 2332 period = PERIOD_800; 2333#ifdef NEO_KHZ400 2334 } else { // 400 KHz bitstream 2335 time0 = TIME_400_0; 2336 time1 = TIME_400_1; 2337 period = PERIOD_400; 2338 } 2339#endif 2340 2341 for(t = time0;; t = time0) { 2342 if(pix & mask) t = time1; 2343 while(*timeValue < period); 2344 *portSet = pinMask; 2345 *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG; 2346 while(*timeValue < t); 2347 *portClear = pinMask; 2348 if(!(mask >>= 1)) { // This 'inside-out' loop logic utilizes 2349 if(p >= end) break; // idle time to minimize inter-byte delays. 2350 pix = *p++; 2351 mask = 0x80; 2352 } 2353 } 2354 while(*timeValue < period); // Wait for last bit 2355 TC_Stop(TC1, 0); 2356 2357#endif // end Due 2358 2359// END ARM ---------------------------------------------------------------- 2360 2361 2362#elif defined(ESP8266) || defined(ESP32) 2363 2364// ESP8266 ---------------------------------------------------------------- 2365 2366 // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution 2367 espShow(pin, pixels, numBytes, is800KHz); 2368 2369#elif defined(__ARDUINO_ARC__) 2370 2371// Arduino 101 ----------------------------------------------------------- 2372 2373#define NOPx7 { __builtin_arc_nop(); \\ 2374 __builtin_arc_nop(); __builtin_arc_nop(); \\ 2375 __builtin_arc_nop(); __builtin_arc_nop(); \\ 2376 __builtin_arc_nop(); __builtin_arc_nop(); } 2377 2378 PinDescription *pindesc = &g_APinDescription[pin]; 2379 register uint32_t loop = 8 * numBytes; // one loop to handle all bytes and all bits 2380 register uint8_t *p = pixels; 2381 register uint32_t currByte = (uint32_t) (*p); 2382 register uint32_t currBit = 0x80 & currByte; 2383 register uint32_t bitCounter = 0; 2384 register uint32_t first = 1; 2385 2386 // The loop is unusual. Very first iteration puts all the way LOW to the wire - 2387 // constant LOW does not affect NEOPIXEL, so there is no visible effect displayed. 2388 // During that very first iteration CPU caches instructions in the loop. 2389 // Because of the caching process, "CPU slows down". NEOPIXEL pulse is very time sensitive 2390 // that's why we let the CPU cache first and we start regular pulse from 2nd iteration 2391 if (pindesc->ulGPIOType == SS_GPIO) { 2392 register uint32_t reg = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR; 2393 uint32_t reg_val = __builtin_arc_lr((volatile uint32_t)reg); 2394 register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId); 2395 register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId); 2396 2397 loop += 1; // include first, special iteration 2398 while(loop--) { 2399 if(!first) { 2400 currByte <<= 1; 2401 bitCounter++; 2402 } 2403 2404 // 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low 2405 __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile uint32_t)reg); 2406 if(currBit) { // ~400ns HIGH (740ns overall) 2407 NOPx7 2408 NOPx7 2409 } 2410 // ~340ns HIGH 2411 NOPx7 2412 __builtin_arc_nop(); 2413 2414 // 820ns LOW; per spec, max allowed low here is 5000ns */ 2415 __builtin_arc_sr(reg_bit_low, (volatile uint32_t)reg); 2416 NOPx7 2417 NOPx7 2418 2419 if(bitCounter >= 8) { 2420 bitCounter = 0; 2421 currByte = (uint32_t) (*++p); 2422 } 2423 2424 currBit = 0x80 & currByte; 2425 first = 0; 2426 } 2427 } else if(pindesc->ulGPIOType == SOC_GPIO) { 2428 register uint32_t reg = pindesc->ulGPIOBase + SOC_GPIO_SWPORTA_DR; 2429 uint32_t reg_val = MMIO_REG_VAL(reg); 2430 register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId); 2431 register uint32_t reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId); 2432 2433 loop += 1; // include first, special iteration 2434 while(loop--) { 2435 if(!first) { 2436 currByte <<= 1; 2437 bitCounter++; 2438 } 2439 MMIO_REG_VAL(reg) = first ? reg_bit_low : reg_bit_high; 2440 if(currBit) { // ~430ns HIGH (740ns overall) 2441 NOPx7 2442 NOPx7 2443 __builtin_arc_nop(); 2444 } 2445 // ~310ns HIGH 2446 NOPx7 2447 2448 // 850ns LOW; per spec, max allowed low here is 5000ns */ 2449 MMIO_REG_VAL(reg) = reg_bit_low; 2450 NOPx7 2451 NOPx7 2452 2453 if(bitCounter >= 8) { 2454 bitCounter = 0; 2455 currByte = (uint32_t) (*++p); 2456 } 2457 2458 currBit = 0x80 & currByte; 2459 first = 0; 2460 } 2461 } 2462 2463#else 2464#error Architecture not supported 2465#endif 2466 2467 2468// END ARCHITECTURE SELECT ------------------------------------------------ 2469 2470#ifndef NRF52 2471 interrupts(); 2472#endif 2473 2474 endTime = micros(); // Save EOD time for latch on next call 2475} 2476 2477// Set the output pin number 2478void Adafruit_NeoPixel::setPin(uint8_t p) { 2479 if(begun && (pin >= 0)) pinMode(pin, INPUT); 2480 pin = p; 2481 if(begun) { 2482 pinMode(p, OUTPUT); 2483 digitalWrite(p, LOW); 2484 } 2485#ifdef __AVR__ 2486 port = portOutputRegister(digitalPinToPort(p)); 2487 pinMask = digitalPinToBitMask(p); 2488#endif 2489} 2490 2491// Set pixel color from separate R,G,B components: 2492void Adafruit_NeoPixel::setPixelColor( 2493 uint16_t n, uint8_t r, uint8_t g, uint8_t b) { 2494 2495 if(n < numLEDs) { 2496 if(brightness) { // See notes in setBrightness() 2497 r = (r * brightness) >> 8; 2498 g = (g * brightness) >> 8; 2499 b = (b * brightness) >> 8; 2500 } 2501 uint8_t *p; 2502 if(wOffset == rOffset) { // Is an RGB-type strip 2503 p = &pixels[n * 3]; // 3 bytes per pixel 2504 } else { // Is a WRGB-type strip 2505 p = &pixels[n * 4]; // 4 bytes per pixel 2506 p[wOffset] = 0; // But only R,G,B passed -- set W to 0 2507 } 2508 p[rOffset] = r; // R,G,B always stored 2509 p[gOffset] = g; 2510 p[bOffset] = b; 2511 } 2512} 2513 2514void Adafruit_NeoPixel::setPixelColor( 2515 uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { 2516 2517 if(n < numLEDs) { 2518 if(brightness) { // See notes in setBrightness() 2519 r = (r * brightness) >> 8; 2520 g = (g * brightness) >> 8; 2521 b = (b * brightness) >> 8; 2522 w = (w * brightness) >> 8; 2523 } 2524 uint8_t *p; 2525 if(wOffset == rOffset) { // Is an RGB-type strip 2526 p = &pixels[n * 3]; // 3 bytes per pixel (ignore W) 2527 } else { // Is a WRGB-type strip 2528 p = &pixels[n * 4]; // 4 bytes per pixel 2529 p[wOffset] = w; // Store W 2530 } 2531 p[rOffset] = r; // Store R,G,B 2532 p[gOffset] = g; 2533 p[bOffset] = b; 2534 } 2535} 2536 2537// Set pixel color from 'packed' 32-bit RGB color: 2538void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) { 2539 if(n < numLEDs) { 2540 uint8_t *p, 2541 r = (uint8_t)(c >> 16), 2542 g = (uint8_t)(c >> 8), 2543 b = (uint8_t)c; 2544 if(brightness) { // See notes in setBrightness() 2545 r = (r * brightness) >> 8; 2546 g = (g * brightness) >> 8; 2547 b = (b * brightness) >> 8; 2548 } 2549 if(wOffset == rOffset) { 2550 p = &pixels[n * 3]; 2551 } else { 2552 p = &pixels[n * 4]; 2553 uint8_t w = (uint8_t)(c >> 24); 2554 p[wOffset] = brightness ? ((w * brightness) >> 8) : w; 2555 } 2556 p[rOffset] = r; 2557 p[gOffset] = g; 2558 p[bOffset] = b; 2559 } 2560} 2561 2562// Convert separate R,G,B into packed 32-bit RGB color. 2563// Packed format is always RGB, regardless of LED strand color order. 2564uint32_t Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) { 2565 return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 2566} 2567 2568// Convert separate R,G,B,W into packed 32-bit WRGB color. 2569// Packed format is always WRGB, regardless of LED strand color order. 2570uint32_t Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { 2571 return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 2572} 2573 2574// Query color from previously-set pixel (returns packed 32-bit RGB value) 2575uint32_t Adafruit_NeoPixel::getPixelColor(uint16_t n) const { 2576 if(n >= numLEDs) return 0; // Out of bounds, return no color. 2577 2578 uint8_t *p; 2579 2580 if(wOffset == rOffset) { // Is RGB-type device 2581 p = &pixels[n * 3]; 2582 if(brightness) { 2583 // Stored color was decimated by setBrightness(). Returned value 2584 // attempts to scale back to an approximation of the original 24-bit 2585 // value used when setting the pixel color, but there will always be 2586 // some error -- those bits are simply gone. Issue is most 2587 // pronounced at low brightness levels. 2588 return (((uint32_t)(p[rOffset] << 8) / brightness) << 16) | 2589 (((uint32_t)(p[gOffset] << 8) / brightness) << 8) | 2590 ( (uint32_t)(p[bOffset] << 8) / brightness ); 2591 } else { 2592 // No brightness adjustment has been made -- return 'raw' color 2593 return ((uint32_t)p[rOffset] << 16) | 2594 ((uint32_t)p[gOffset] << 8) | 2595 (uint32_t)p[bOffset]; 2596 } 2597 } else { // Is RGBW-type device 2598 p = &pixels[n * 4]; 2599 if(brightness) { // Return scaled color 2600 return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) | 2601 (((uint32_t)(p[rOffset] << 8) / brightness) << 16) | 2602 (((uint32_t)(p[gOffset] << 8) / brightness) << 8) | 2603 ( (uint32_t)(p[bOffset] << 8) / brightness ); 2604 } else { // Return raw color 2605 return ((uint32_t)p[wOffset] << 24) | 2606 ((uint32_t)p[rOffset] << 16) | 2607 ((uint32_t)p[gOffset] << 8) | 2608 (uint32_t)p[bOffset]; 2609 } 2610 } 2611} 2612 2613// Returns pointer to pixels[] array. Pixel data is stored in device- 2614// native format and is not translated here. Application will need to be 2615// aware of specific pixel data format and handle colors appropriately. 2616uint8_t *Adafruit_NeoPixel::getPixels(void) const { 2617 return pixels; 2618} 2619 2620uint16_t Adafruit_NeoPixel::numPixels(void) const { 2621 return numLEDs; 2622} 2623 2624// Adjust output brightness; 0=darkest (off), 255=brightest. This does 2625// NOT immediately affect what's currently displayed on the LEDs. The 2626// next call to show() will refresh the LEDs at this level. However, 2627// this process is potentially "lossy," especially when increasing 2628// brightness. The tight timing in the WS2811/WS2812 code means there 2629// aren't enough free cycles to perform this scaling on the fly as data 2630// is issued. So we make a pass through the existing color data in RAM 2631// and scale it (subsequent graphics commands also work at this 2632// brightness level). If there's a significant step up in brightness, 2633// the limited number of steps (quantization) in the old data will be 2634// quite visible in the re-scaled version. For a non-destructive 2635// change, you'll need to re-render the full strip data. C'est la vie. 2636void Adafruit_NeoPixel::setBrightness(uint8_t b) { 2637 // Stored brightness value is different than what's passed. 2638 // This simplifies the actual scaling math later, allowing a fast 2639 // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t, 2640 // adding 1 here may (intentionally) roll over...so 0 = max brightness 2641 // (color values are interpreted literally; no scaling), 1 = min 2642 // brightness (off), 255 = just below max brightness. 2643 uint8_t newBrightness = b + 1; 2644 if(newBrightness != brightness) { // Compare against prior value 2645 // Brightness has changed -- re-scale existing data in RAM 2646 uint8_t c, 2647 *ptr = pixels, 2648 oldBrightness = brightness - 1; // De-wrap old brightness value 2649 uint16_t scale; 2650 if(oldBrightness == 0) scale = 0; // Avoid /0 2651 else if(b == 255) scale = 65535 / oldBrightness; 2652 else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; 2653 for(uint16_t i=0; i<numBytes; i++) { 2654 c = *ptr; 2655 *ptr++ = (c * scale) >> 8; 2656 } 2657 brightness = newBrightness; 2658 } 2659} 2660 2661//Return the brightness value 2662uint8_t Adafruit_NeoPixel::getBrightness(void) const { 2663 return brightness - 1; 2664} 2665 2666void Adafruit_NeoPixel::clear() { 2667 memset(pixels, 0, numBytes); 2668} 2669
RX8025.h
c_cpp
1#ifndef __RX8025_H__ 2#define __RX8025_H__ 3 4#define Set_Bit(P,N) P |= (1<<N) 5#define Clear_Bit(P,N) P &=~(1<<N) 6 7//PC1 SDA /*I2C */ 8 9#define SCL_OUT() Set_Bit(DDRC,5) 10#define SCL_IN() Clear_Bit(DDRC,5) 11#define SCL_H() Set_Bit(PORTC,5) 12#define SCL_L() Clear_Bit(PORTC,5) 13 14#define SDA_OUT() Set_Bit(DDRC,4) 15#define SDA_IN() Clear_Bit(DDRC,4) 16#define SDA_H() Set_Bit(PORTC,4) 17#define SDA_L() Clear_Bit(PORTC,4) 18 19#define SDA_INPUT() !(!(PINC & 0x10)) 20 21#define RX8025_ADD 0x64 // RX8025I2C 22#define RS8025_TIME_REG_START_ADD 0X00 //RX8050 23#define RS8025_CONTROL_REG_ADD 0XE0 //RX8050 24 25void Start_I2c(); 26void Stop_I2c(); 27void SendByte(unsigned char c); 28unsigned char RcvByte(); 29void Ack_I2c(unsigned char a); 30unsigned char ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no); 31unsigned char IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no); 32void RX8025_INIT (void); 33void RX8025_READ (unsigned char *GetTime); 34void RX8025_WRITE (unsigned char *SetTime); 35 36#endif 37
key.cpp
c_cpp
1/* 2 * key.cpp 3 * 4 * Created on: 201858 5 * Author: 6 */ 7 8 #include "key.h" 9 #include <avr/io.h> 10 #include <util/delay.h> 11 #include <avr/interrupt.h> 12 13 unsigned char timer_10ms_flag = 0; 14 //unsigned char key; 15 16 /*********************** 17 * T2 18 */ 19 void key_init(){ 20 DDRD &= 0x1F; 21 PORTD |= 0xE0; // PD5,PD6,PD7 22 TCCR2 = 0x07; // 2, 256 23 TCNT2 = 0x00; // 24 OCR2 = 0x9C; // 25 TIMSK |= 0x80; 26 sei(); 27 } 28 29 /*********************** 30 * 31 */ 32 static unsigned char key_driver(unsigned char nnn){ 33 static unsigned char key_state_buffer1[3] = {key_state_0,key_state_0,key_state_0}; 34 static unsigned char key_timer_cnt1[3] = {0,0,0}; 35 static unsigned char key_return[3] = {key_no,key_no,key_no}; 36 unsigned char key; 37 38key_return[2]=key_no; // 39 // 40 // 41 42 key = key_input(nnn); 43 if(key == 1)key_return[nnn] = key_no; 44 switch(key_state_buffer1[nnn]) 45 { 46 case key_state_0: 47 if(key == 0) 48 key_state_buffer1[nnn] = key_state_1; 49 //// 50 break; 51 case key_state_1: 52 if(key == 0) 53 { 54 key_timer_cnt1[nnn] = 0; 55 key_state_buffer1[nnn] = key_state_2; 56 // 57 //key_timer 58 // 59 } 60 else 61 key_state_buffer1[nnn] = key_state_0; 62 // 63 break; // 64 case key_state_2: 65 if(key == 1) 66 { 67 key_return[nnn] = key_click; //click 68 key_state_buffer1[nnn] = key_state_0; // 69 } 70 else if(++key_timer_cnt1[nnn] >= 100) //1000ms 71 { 72 key_return[nnn] = key_long; // 73 key_state_buffer1[nnn] = key_state_3; // 74 } 75 break; 76 case key_state_3: // 77 if(key == 1) // 78 key_state_buffer1[nnn] = key_state_0; // 79 break; 80 } 81 return key_return[nnn]; 82 } 83 84 /************************ 85 * 86 */ 87 unsigned char key_read(unsigned char nnn){ 88 static unsigned char key_state_buffer2[3] = {key_state_0,key_state_0,key_state_0}; 89 static unsigned char key_timer_cnt2[3] = {0,0,0}; 90 unsigned char key_return = key_no; 91 unsigned char key; 92 93 key = key_driver(nnn); 94 switch(key_state_buffer2[nnn]) 95 { 96 case key_state_0: 97 if(key == key_click) 98 { 99 key_timer_cnt2[nnn] = 0; // 100 key_state_buffer2[nnn] = key_state_1; 101 } 102 else 103 key_return = key; // 104 break; 105 case key_state_1: 106 if(key == key_click) //500ms 107 { 108 key_return = key_double; // 109 key_state_buffer2[nnn] = key_state_0; 110 } 111 else if(++key_timer_cnt2[nnn] >= 50) 112 { 113 //500ms1000ms 114 //1s 115 116 key_return = key_click; //500ms 117 key_state_buffer2[nnn] = key_state_0; // 118 } 119 break; 120 } 121 122 return key_return; 123 } 124/************************************************************** 125 * 126 */ 127unsigned char key_input(unsigned char nnn) 128{ 129 if(((PIND>>(5+nnn)) & 0x01) == 0) 130 { 131 _delay_ms(5); // 10ms 132 if(((PIND>>(5+nnn)) & 0x01) == 0) 133 return 0; 134 } 135 else 136 return 1; 137} 138 /************************* 139 * 140 */ 141 ISR(TIMER2_COMP_vect){ 142 TCNT2 = 0x00; 143 timer_10ms_flag |= key_flag; //reset time 10ms flag 144 } 145
Adafruit_NeoPixel.h
c_cpp
1/*-------------------------------------------------------------------- 2 This file is part of the Adafruit NeoPixel library. 3 4 NeoPixel is free software: you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation, either version 3 of 7 the License, or (at your option) any later version. 8 9 NeoPixel is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with NeoPixel. If not, see 16 <http://www.gnu.org/licenses/>. 17 --------------------------------------------------------------------*/ 18 19#ifndef ADAFRUIT_NEOPIXEL_H 20#define ADAFRUIT_NEOPIXEL_H 21 22#if (ARDUINO >= 100) 23 #include <Arduino.h> 24#else 25 #include <WProgram.h> 26 #include <pins_arduino.h> 27#endif 28 29// The order of primary colors in the NeoPixel data stream can vary 30// among device types, manufacturers and even different revisions of 31// the same item. The third parameter to the Adafruit_NeoPixel 32// constructor encodes the per-pixel byte offsets of the red, green 33// and blue primaries (plus white, if present) in the data stream -- 34// the following #defines provide an easier-to-use named version for 35// each permutation. e.g. NEO_GRB indicates a NeoPixel-compatible 36// device expecting three bytes per pixel, with the first byte 37// containing the green value, second containing red and third 38// containing blue. The in-memory representation of a chain of 39// NeoPixels is the same as the data-stream order; no re-ordering of 40// bytes is required when issuing data to the chain. 41 42// Bits 5,4 of this value are the offset (0-3) from the first byte of 43// a pixel to the location of the red color byte. Bits 3,2 are the 44// green offset and 1,0 are the blue offset. If it is an RGBW-type 45// device (supporting a white primary in addition to R,G,B), bits 7,6 46// are the offset to the white byte...otherwise, bits 7,6 are set to 47// the same value as 5,4 (red) to indicate an RGB (not RGBW) device. 48// i.e. binary representation: 49// 0bWWRRGGBB for RGBW devices 50// 0bRRRRGGBB for RGB 51 52// RGB NeoPixel permutations; white and red offsets are always same 53// Offset: W R G B 54#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2)) 55#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1)) 56#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2)) 57#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1)) 58#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0)) 59#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0)) 60 61// RGBW NeoPixel permutations; all 4 offsets are distinct 62// Offset: W R G B 63#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3)) 64#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2)) 65#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3)) 66#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2)) 67#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1)) 68#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1)) 69 70#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3)) 71#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2)) 72#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3)) 73#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2)) 74#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1)) 75#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1)) 76 77#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3)) 78#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2)) 79#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3)) 80#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2)) 81#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1)) 82#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1)) 83 84#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0)) 85#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0)) 86#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0)) 87#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0)) 88#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0)) 89#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0)) 90 91// Add NEO_KHZ400 to the color order value to indicate a 400 KHz 92// device. All but the earliest v1 NeoPixels expect an 800 KHz data 93// stream, this is the default if unspecified. Because flash space 94// is very limited on ATtiny devices (e.g. Trinket, Gemma), v1 95// NeoPixels aren't handled by default on those chips, though it can 96// be enabled by removing the ifndef/endif below -- but code will be 97// bigger. Conversely, can disable the NEO_KHZ400 line on other MCUs 98// to remove v1 support and save a little space. 99 100#define NEO_KHZ800 0x0000 // 800 KHz datastream 101#ifndef __AVR_ATtiny85__ 102#define NEO_KHZ400 0x0100 // 400 KHz datastream 103#endif 104 105// If 400 KHz support is enabled, the third parameter to the constructor 106// requires a 16-bit value (in order to select 400 vs 800 KHz speed). 107// If only 800 KHz is enabled (as is default on ATtiny), an 8-bit value 108// is sufficient to encode pixel color order, saving some space. 109 110#ifdef NEO_KHZ400 111typedef uint16_t neoPixelType; 112#else 113typedef uint8_t neoPixelType; 114#endif 115 116class Adafruit_NeoPixel { 117 118 public: 119 120 // Constructor: number of LEDs, pin number, LED type 121 Adafruit_NeoPixel(uint16_t n, uint8_t p=6, neoPixelType t=NEO_GRB + NEO_KHZ800); 122 Adafruit_NeoPixel(void); 123 ~Adafruit_NeoPixel(); 124 125 void 126 begin(void), 127 show(void), 128 setPin(uint8_t p), 129 setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), 130 setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w), 131 setPixelColor(uint16_t n, uint32_t c), 132 setBrightness(uint8_t), 133 clear(), 134 updateLength(uint16_t n), 135 updateType(neoPixelType t); 136 uint8_t 137 *getPixels(void) const, 138 getBrightness(void) const; 139 int8_t 140 getPin(void) { return pin; }; 141 uint16_t 142 numPixels(void) const; 143 static uint32_t 144 Color(uint8_t r, uint8_t g, uint8_t b), 145 Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w); 146 uint32_t 147 getPixelColor(uint16_t n) const; 148 inline bool 149 canShow(void) { return (micros() - endTime) >= 300L; } 150 151 protected: 152 153 boolean 154#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled... 155 is800KHz, // ...true if 800 KHz pixels 156#endif 157 begun; // true if begin() previously called 158 uint16_t 159 numLEDs, // Number of RGB LEDs in strip 160 numBytes; // Size of 'pixels' buffer below (3 or 4 bytes/pixel) 161 int8_t 162 pin; // Output pin number (-1 if not yet set) 163 uint8_t 164 brightness, 165 *pixels, // Holds LED color values (3 or 4 bytes each) 166 rOffset, // Index of red byte within each 3- or 4-byte pixel 167 gOffset, // Index of green byte 168 bOffset, // Index of blue byte 169 wOffset; // Index of white byte (same as rOffset if no white) 170 uint32_t 171 endTime; // Latch timing reference 172#ifdef __AVR__ 173 volatile uint8_t 174 *port; // Output PORT register 175 uint8_t 176 pinMask; // Output PORT bitmask 177#endif 178}; 179 180#endif // ADAFRUIT_NEOPIXEL_H 181
light.h
c_cpp
1#ifndef LIGHT_H 2#define LIGHT_H 3 4 5struct color{ 6 unsigned char r; 7 unsigned char g; 8 unsigned char b; 9}; 10 11extern color rgb[6]; 12 13void light_init(); 14void poeron_effect(); 15void effect4(); 16void light_wirte(unsigned char* number,color* rgb); 17 18void make_color(color *p,unsigned char c_n); 19void wheel(color* p); 20 21#endif 22
main
arduino
1#include <avr/io.h> 2#include <EEPROM.h> 3#include "clock.h" 4#include "key.h" 5#include "light.h" 6 7#define OFF 0 8#define TIME 1 9#define SET 2 10#define EFFECT1 3 11#define EFFECT2 4 12#define EFFECT3 5 13#define EFFECT4 6 14 15extern unsigned char timer_10ms_flag; 16unsigned char key; 17unsigned char _t[6]={1,1,3,7,3,0}; 18unsigned char color_number; 19unsigned char mode = TIME; //工作模式 20 21#define SETED 0xAA /*出厂第一次设置标志*/ 22 23 24 25void setup() { 26 unsigned char color_number_reset = EEPROM.read(0x01); // 如果0x01内值为SETED则已经完成初始化 27 if(color_number_reset != SETED) // 否则出厂设置 28 { 29 EEPROM.write(0x00,230); // 辉光管颜色值 30 EEPROM.write(0x01,SETED); // 标记已经完成初始化 31 } 32 color_number = EEPROM.read(0x00); 33 34 delay(100); 35 key_init(); 36 light_init(); 37 clock_init(); 38 39 make_color(&rgb[0],color_number); 40 for(unsigned char i=1;i<6;i++){ 41 rgb[i] = rgb[0]; 42 } 43 poeron_effect();//开机动画 44} 45 46void loop() { 47 static unsigned long timesOfLoop = 0; 48 static unsigned char effect2Num = 0; 49 50 if(millis()-timesOfLoop>100) 51 { 52 switch(mode) 53 { 54 case TIME: 55 clock_read(_t); 56 light_wirte(_t,rgb); 57 break; 58 case OFF: 59 break; 60 case SET: 61 break; 62 case EFFECT1://渐变彩虹 63 clock_read(_t); 64 wheel(rgb);wheel(rgb);wheel(rgb); 65 light_wirte(_t,rgb); 66 break; 67 case EFFECT2://慢刷 68 wheel(rgb); 69 for(unsigned char i=1;i<6;i++)rgb[i] = rgb[0]; 70 effect2Num++;effect2Num %= 20; 71 for(unsigned char i=0;i<6;i++)_t[i]=effect2Num>>1; 72 light_wirte(_t,rgb); 73 break; 74 case EFFECT3://快刷 75 effect2Num++;effect2Num %= 10; 76 for(unsigned char i=0;i<6;i++)_t[i]=effect2Num; 77 light_wirte(_t,rgb); 78 delay(49); 79 effect2Num++;effect2Num %= 10; 80 for(unsigned char i=0;i<6;i++)_t[i]=effect2Num; 81 light_wirte(_t,rgb); 82 break; 83 case EFFECT4://相对刷 84 effect4(); 85 break; 86 } 87 timesOfLoop = millis(); 88 } 89 90 if(timer_10ms_flag&key_flag == 1) 91 { 92 timer_10ms_flag &= clear_key_flag; 93 //读第一个按键 94 key = key_read(0); 95 96 switch(key) 97 { 98 case key_click: 99 color_dec(); 100 break; 101 case key_double: 102 color_dec();color_dec(); 103 break; 104 case key_long: 105 color_dec(); 106 break; 107 default: 108 break; 109 } 110 111 //读第二个按键 112 key = key_read(1); 113 114 switch(key) 115 { 116 case key_click: 117 color_inc(); 118 break; 119 case key_double: 120 color_inc();color_inc(); 121 break; 122 case key_long: 123 color_inc(); 124 break; 125 default: 126 break; 127 } 128 129 //读第三个按键 130 key = key_read(2); 131 132 switch(key) 133 { 134 case key_click: 135 power(); 136 break; 137 case key_double: 138 modde_effect(); 139 break; 140 case key_long: 141 time_set(); 142 break; 143 default: 144 break; 145 } 146 } 147} 148 149void color_dec() 150{ 151 make_color(&rgb[0],--color_number); 152 for(unsigned char i=1;i<6;i++){ 153 rgb[i] = rgb[0]; 154 } 155 //light_wirte(_t,rgb); 156 EEPROM.write(0x00,color_number); // 更新辉光管颜色值 157} 158 159void color_inc() 160{ 161 make_color(&rgb[0],++color_number); 162 for(unsigned char i=1;i<6;i++){ 163 rgb[i] = rgb[0]; 164 } 165 //light_wirte(_t,rgb); 166 EEPROM.write(0x00,color_number); // 更新辉光管颜色值 167} 168 169void power() 170{ 171 static unsigned char n = 0; 172 if((n & 0x01) == 0) 173 { 174 mode = OFF; 175 for(unsigned char i=0;i<6;i++) 176 rgb[i] = {0,0,0}; 177 light_wirte(_t,rgb); 178 } 179 else 180 { 181 mode =TIME; 182 make_color(&rgb[0],color_number); 183 for(unsigned char i=1;i<6;i++){ 184 rgb[i] = rgb[0]; 185 } 186 clock_read(_t); 187 light_wirte(_t,rgb); 188 } 189 n++; 190} 191 192void modde_effect() 193{ 194 static unsigned char n = 0; 195 n++; 196 switch(n % 5) 197 { 198 case 0: 199 make_color(&rgb[0],color_number); 200 for(unsigned char i=1;i<6;i++){ 201 rgb[i] = rgb[0]; 202 } 203 mode = TIME; 204 break; 205 case 1: 206 mode = EFFECT1; 207 break; 208 case 2: 209 mode = EFFECT2; 210 break; 211 case 3: 212 make_color(&rgb[0],color_number); 213 for(unsigned char i=1;i<6;i++){ 214 rgb[i] = rgb[0]; 215 } 216 mode = EFFECT3; 217 break; 218 case 4: 219 mode = EFFECT4; 220 break; 221 } 222} 223 224void time_set() 225{ 226 EEPROM.write(0x00,230); // 辉光管颜色值 227 color_number = 230; 228 make_color(&rgb[0],color_number); 229 for(unsigned char i=1;i<6;i++){ 230 rgb[i] = rgb[0]; 231 } 232 //power(); 233} 234
key.cpp
c_cpp
1/* 2 * key.cpp 3 * 4 * Created on: 201858 5 * Author: 6 7 */ 8 9 #include "key.h" 10 #include <avr/io.h> 11 #include <util/delay.h> 12 13 #include <avr/interrupt.h> 14 15 unsigned char timer_10ms_flag = 0; 16 //unsigned 17 char key; 18 19 /*********************** 20 * T2 21 */ 22 void key_init(){ 23 24 DDRD &= 0x1F; 25 PORTD |= 0xE0; // PD5,PD6,PD7 26 TCCR2 = 0x07; // 2, 256 27 28 TCNT2 = 0x00; // 29 OCR2 = 0x9C; // 30 TIMSK |= 0x80; 31 sei(); 32 33 } 34 35 /*********************** 36 * 37 */ 38 static unsigned char key_driver(unsigned 39 char nnn){ 40 static unsigned char key_state_buffer1[3] = {key_state_0,key_state_0,key_state_0}; 41 static 42 unsigned char key_timer_cnt1[3] = {0,0,0}; 43 static unsigned char key_return[3] 44 = {key_no,key_no,key_no}; 45 unsigned char key; 46 47key_return[2]=key_no; // 48 49 // 50 // 51 52 key = key_input(nnn); 53 54 if(key == 1)key_return[nnn] = key_no; 55 switch(key_state_buffer1[nnn]) 56 { 57 case 58 key_state_0: 59 if(key == 0) 60 key_state_buffer1[nnn] = key_state_1; 61 62 //// 63 break; 64 case key_state_1: 65 if(key == 0) 66 { 67 key_timer_cnt1[nnn] 68 = 0; 69 key_state_buffer1[nnn] = key_state_2; 70 // 71 //key_timer 72 // 73 } 74 else 75 key_state_buffer1[nnn] 76 = key_state_0; 77 // 78 break; // 79 case key_state_2: 80 if(key 81 == 1) 82 { 83 key_return[nnn] = key_click; //click 84 key_state_buffer1[nnn] 85 = key_state_0; // 86 } 87 else if(++key_timer_cnt1[nnn] >= 100) //1000ms 88 { 89 key_return[nnn] 90 = key_long; // 91 key_state_buffer1[nnn] = key_state_3; // 92 } 93 break; 94 case 95 key_state_3: // 96 if(key == 1) // 97 key_state_buffer1[nnn] = 98 key_state_0; // 99 break; 100 } 101 return key_return[nnn]; 102 } 103 104 105 /************************ 106 * 107 */ 108 unsigned char key_read(unsigned char 109 nnn){ 110 static unsigned char key_state_buffer2[3] = {key_state_0,key_state_0,key_state_0}; 111 static 112 unsigned char key_timer_cnt2[3] = {0,0,0}; 113 unsigned char key_return = key_no; 114 unsigned 115 char key; 116 117 key = key_driver(nnn); 118 switch(key_state_buffer2[nnn]) 119 { 120 case 121 key_state_0: 122 if(key == key_click) 123 { 124 key_timer_cnt2[nnn] 125 = 0; // 126 key_state_buffer2[nnn] = key_state_1; 127 } 128 else 129 130 key_return = key; // 131 break; 132 case key_state_1: 133 if(key 134 == key_click) //500ms 135 { 136 key_return = key_double; // 137 key_state_buffer2[nnn] 138 = key_state_0; 139 } 140 else if(++key_timer_cnt2[nnn] >= 50) 141 { 142 //500ms1000ms 143 //1s 144 145 key_return 146 = key_click; //500ms 147 key_state_buffer2[nnn] = key_state_0; // 148 } 149 break; 150 } 151 152 return 153 key_return; 154 } 155/************************************************************** 156 157 * 158 */ 159unsigned char key_input(unsigned char nnn) 160{ 161 if(((PIND>>(5+nnn)) 162 & 0x01) == 0) 163 { 164 _delay_ms(5); // 10ms 165 if(((PIND>>(5+nnn)) 166 & 0x01) == 0) 167 return 0; 168 } 169 else 170 return 1; 171} 172 173 /************************* 174 * 175 */ 176 ISR(TIMER2_COMP_vect){ 177 TCNT2 178 = 0x00; 179 timer_10ms_flag |= key_flag; //reset time 10ms flag 180 } 181
RX8025.cpp
c_cpp
1#include<stdio.h> 2#include <avr/io.h> 3#include <util/delay.h> 4#include 5 "RX8025.h" 6 7unsigned char ack; /**/ 8 9/******************************************************************* 10 11: 12 void Start_I2c(); 13: I2C ,I2C . 14********************************************************************/ 15void 16 Start_I2c() 17{ 18 SCL_OUT(); 19 SCL_L(); 20 SDA_OUT();/**/ 21 _delay_us(5); 22 23 SDA_H(); /**/ 24 _delay_us(5); 25 SCL_H(); /**/ 26 _delay_us(6); /*4.7us,*/ 27 SDA_L(); 28 /**/ 29 _delay_us(6); /* 4s*/ 30 SCL_L(); /*I2C */ 31 _delay_us(2); 32} 33/******************************************************************* 34 35: 36 void Stop_I2c(); 37: I2C ,I2C . 38********************************************************************/ 39void 40 Stop_I2c() 41{ 42 SCL_OUT(); 43 SCL_L(); 44 _delay_us(6); 45 SDA_OUT();/**/ 46 SDA_L() 47 ; /**/ 48 _delay_us(6); 49 SCL_H(); /*4s*/ 50 _delay_us(6); 51 SDA_H(); 52 /*I2C */ 53 _delay_us(6); 54 SCL_L(); 55} 56/******************************************************************* 57 58: 59 void SendByte(uchar c); 60: c ,,,, 61.(ack=0 ) 62ack=1; ack=0 63********************************************************************/ 64void 65 SendByte(unsigned char c) 66{ 67 unsigned char BitCnt =0; 68 SCL_OUT(); 69 SDA_OUT();/**/ 70 71 for(BitCnt 72 = 0; BitCnt < 8; BitCnt++){ /*8 */ 73 SCL_L(); 74 _delay_us(6); 75 if((c 76 << BitCnt) & 0x80) SDA_H(); /**/ 77 else SDA_L(); 78 _delay_us(6); 79 SCL_H(); 80 /**/ 81 _delay_us(5); /*4s*/ 82 SCL_L(); 83 _delay_us(6); 84 } 85 SDA_H(); 86 /*8 */ 87 SDA_IN();/**/ 88 _delay_us(1); 89 SCL_H(); 90 _delay_us(3); 91 if(1 92 == SDA_INPUT()) 93 { 94 ack = 0;/**/ 95 } 96 else ack=1; /**/ 97 SCL_L(); 98 _delay_us(3); 99} 100/******************************************************************* 101 102: 103 uchar RcvByte(); 104: ,() 105 106********************************************************************/ 107unsigned 108 char RcvByte() 109{ 110 unsigned char retc = 0; 111 unsigned char BitCnt = 0; 112 SCL_OUT(); 113 SDA_OUT(); 114 SCL_L(); 115 _delay_us(6); 116 SDA_H(); 117 /**/ 118 _delay_us(2); 119 SDA_IN();/**/ 120 for(BitCnt = 0; BitCnt < 8; BitCnt++) 121 { 122 _delay_us(1); 123 SCL_L(); 124 /**/ 125 _delay_us(6); /*4.7s*/ 126 SCL_H(); /**/ 127 _delay_us(1); 128 retc 129 = (retc << 1); 130 if(1 == SDA_INPUT()) 131 retc = (retc + 1); /*,retc */ 132 } 133 SCL_L(); 134 _delay_us(1); 135 //_delay_us(1); 136 return(retc); 137} 138/******************************************************************** 139 140: 141 void Ack_I2c(bit a); 142:,() 143********************************************************************/ 144void 145 Ack_I2c(unsigned char a) 146{ 147 SDA_OUT(); 148 if(a == 0) SDA_L(); /* */ 149 else 150 SDA_H(); 151 _delay_us(3); 152 SCL_H(); 153 _delay_us(5); /*4s*/ 154 SCL_L(); 155 /*I2C */ 156 _delay_us(2); 157} 158/******************************************************************* 159 160: 161 bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); 162: ,, 163slasubas no 1641 165 166 167********************************************************************/ 168unsigned 169 char ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char 170 no) 171{ 172 unsigned char i; 173 Start_I2c(); /**/ 174 SendByte(sla); /**/ 175 if(ack 176 == 0) return(0); 177 SendByte(suba); /**/ 178 if(ack == 0) return(0); 179 for(i 180 = 0; i < no; i++){ 181 SendByte(*s); /**/ 182 if(ack == 0) return(0); 183 s++; 184 } 185 Stop_I2c(); 186 /**/ 187 return(1); 188} 189/******************************************************************* 190 191: 192 bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no); 193: ,, 194slasubas no 1951 196 197 198********************************************************************/ 199unsigned 200 char IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char 201 no) 202{ 203 unsigned char i; 204 Start_I2c(); /**/ 205 SendByte(sla); /**/ 206 if(ack 207 == 0) return(0); 208 SendByte(suba); /**/ 209 if(ack == 0) return(0); 210 Start_I2c(); 211 SendByte(sla 212 + 1); 213 if(ack == 0) return(0); 214 for(i = 0; i< no - 1; i++){ 215 *s = 216 RcvByte(); /**/ 217 Ack_I2c(0); /**/ 218 s++; 219 _delay_us(1); 220 _delay_us(1); 221 } 222 *s 223 = RcvByte(); 224 Ack_I2c(1); /**/ 225 Stop_I2c(); /**/ 226 return(1); 227} 228/********************************************************************************************* 229RX8025 230 231 RX8025_INIT(); 232 233 234 7 235 7unsigned char YY,MO,DD,WW,HH,MM,SS; // 236**********************************************************************************************/ 237void 238 RX8025_INIT(void) 239{ // 240 unsigned char buf[7]; // 241 IRcvStr(RX8025_ADD,RS8025_CONTROL_REG_ADD,buf,2); 242 // 243 if(buf[1] & 0x10){ //C10x01 244 buf[0] |= 0x20; //24 245 buf[1] &= 246 0xEF; //PON 247 ISendStr(RX8025_ADD,RS8025_CONTROL_REG_ADD,buf,2); // 248 } 249} 250/********************************************************************************************* 251RX8025 252 253 RX8025_READ(); 254 255 256 ( 257**********************************************************************************************/ 258void 259 RX8025_READ (unsigned char *GetTime) 260{ 261 unsigned char _time[3]; 262 IRcvStr(RX8025_ADD,RS8025_TIME_REG_START_ADD,_time,3); 263 // 264 GetTime[0] = _time[2] >> 4; 265 GetTime[1] = _time[2] & 0x0F; 266 GetTime[2] 267 = _time[1] >> 4; 268 GetTime[3] = _time[1] & 0x0F; 269 GetTime[4] = _time[0] >> 270 4; 271 GetTime[5] = _time[0] & 0x0F; 272} 273/********************************************************************************************* 274RX8025 275 276 RX8025_WRITE(); 277 278 279 7 280**********************************************************************************************/ 281void 282 RX8025_WRITE (unsigned char *SetTime) 283{ 284 unsigned char _time[3]; 285 _time[2] 286 = (SetTime[0] << 4) | SetTime[1]; 287 _time[1] = (SetTime[2] << 4) | SetTime[3]; 288 _time[0] 289 = (SetTime[4] << 4) | SetTime[5]; 290 ISendStr(RX8025_ADD,RS8025_TIME_REG_START_ADD,_time,3); 291 // 292} 293
main
arduino
1#include <avr/io.h> 2#include <EEPROM.h> 3#include "clock.h" 4#include 5 "key.h" 6#include "light.h" 7 8#define OFF 0 9#define TIME 1 10#define 11 SET 2 12#define EFFECT1 3 13#define EFFECT2 4 14#define EFFECT3 5 15#define 16 EFFECT4 6 17 18extern unsigned char timer_10ms_flag; 19unsigned char key; 20unsigned 21 char _t[6]={1,1,3,7,3,0}; 22unsigned char color_number; 23unsigned char mode = 24 TIME; //工作模式 25 26#define SETED 0xAA /*出厂第一次设置标志*/ 27 28 29 30void setup() 31 { 32 unsigned char color_number_reset = EEPROM.read(0x01); // 如果0x01内值为SETED则已经完成初始化 33 34 if(color_number_reset != SETED) // 否则出厂设置 35 { 36 EEPROM.write(0x00,230); 37 // 辉光管颜色值 38 EEPROM.write(0x01,SETED); // 标记已经完成初始化 39 } 40 color_number 41 = EEPROM.read(0x00); 42 43 delay(100); 44 key_init(); 45 light_init(); 46 47 clock_init(); 48 49 make_color(&rgb[0],color_number); 50 for(unsigned char 51 i=1;i<6;i++){ 52 rgb[i] = rgb[0]; 53 } 54 poeron_effect();//开机动画 55} 56 57void 58 loop() { 59 static unsigned long timesOfLoop = 0; 60 static unsigned char 61 effect2Num = 0; 62 63 if(millis()-timesOfLoop>100) 64 { 65 switch(mode) 66 67 { 68 case TIME: 69 clock_read(_t); 70 light_wirte(_t,rgb); 71 72 break; 73 case OFF: 74 break; 75 case SET: 76 77 break; 78 case EFFECT1://渐变彩虹 79 clock_read(_t); 80 81 wheel(rgb);wheel(rgb);wheel(rgb); 82 light_wirte(_t,rgb); 83 84 break; 85 case EFFECT2://慢刷 86 wheel(rgb); 87 for(unsigned 88 char i=1;i<6;i++)rgb[i] = rgb[0]; 89 effect2Num++;effect2Num %= 20; 90 91 for(unsigned char i=0;i<6;i++)_t[i]=effect2Num>>1; 92 light_wirte(_t,rgb); 93 94 break; 95 case EFFECT3://快刷 96 effect2Num++;effect2Num 97 %= 10; 98 for(unsigned char i=0;i<6;i++)_t[i]=effect2Num; 99 light_wirte(_t,rgb); 100 101 delay(49); 102 effect2Num++;effect2Num %= 10; 103 for(unsigned 104 char i=0;i<6;i++)_t[i]=effect2Num; 105 light_wirte(_t,rgb); 106 break; 107 108 case EFFECT4://相对刷 109 effect4(); 110 break; 111 } 112 113 timesOfLoop = millis(); 114 } 115 116 if(timer_10ms_flag&key_flag == 1) 117 118 { 119 timer_10ms_flag &= clear_key_flag; 120 //读第一个按键 121 key = 122 key_read(0); 123 124 switch(key) 125 { 126 case key_click: 127 128 color_dec(); 129 break; 130 case key_double: 131 color_dec();color_dec(); 132 133 break; 134 case key_long: 135 color_dec(); 136 break; 137 138 default: 139 break; 140 } 141 142 //读第二个按键 143 key = key_read(1); 144 145 146 switch(key) 147 { 148 case key_click: 149 color_inc(); 150 151 break; 152 case key_double: 153 color_inc();color_inc(); 154 155 break; 156 case key_long: 157 color_inc(); 158 break; 159 160 default: 161 break; 162 } 163 164 //读第三个按键 165 key = key_read(2); 166 167 168 switch(key) 169 { 170 case key_click: 171 power(); 172 173 break; 174 case key_double: 175 modde_effect(); 176 break; 177 178 case key_long: 179 time_set(); 180 break; 181 default: 182 183 break; 184 } 185 } 186} 187 188void color_dec() 189{ 190 make_color(&rgb[0],--color_number); 191 192 for(unsigned char i=1;i<6;i++){ 193 rgb[i] = rgb[0]; 194 } 195 //light_wirte(_t,rgb); 196 197 EEPROM.write(0x00,color_number); // 更新辉光管颜色值 198} 199 200void color_inc() 201{ 202 203 make_color(&rgb[0],++color_number); 204 for(unsigned char i=1;i<6;i++){ 205 206 rgb[i] = rgb[0]; 207 } 208 //light_wirte(_t,rgb); 209 EEPROM.write(0x00,color_number); 210 // 更新辉光管颜色值 211} 212 213void power() 214{ 215 static unsigned char n = 0; 216 if((n 217 & 0x01) == 0) 218 { 219 mode = OFF; 220 for(unsigned char i=0;i<6;i++) 221 222 rgb[i] = {0,0,0}; 223 light_wirte(_t,rgb); 224 } 225 else 226 { 227 228 mode =TIME; 229 make_color(&rgb[0],color_number); 230 for(unsigned char 231 i=1;i<6;i++){ 232 rgb[i] = rgb[0]; 233 } 234 clock_read(_t); 235 light_wirte(_t,rgb); 236 237 } 238 n++; 239} 240 241void modde_effect() 242{ 243 static unsigned char n = 244 0; 245 n++; 246 switch(n % 5) 247 { 248 case 0: 249 make_color(&rgb[0],color_number); 250 251 for(unsigned char i=1;i<6;i++){ 252 rgb[i] = rgb[0]; 253 } 254 mode 255 = TIME; 256 break; 257 case 1: 258 mode = EFFECT1; 259 break; 260 case 261 2: 262 mode = EFFECT2; 263 break; 264 case 3: 265 make_color(&rgb[0],color_number); 266 267 for(unsigned char i=1;i<6;i++){ 268 rgb[i] = rgb[0]; 269 } 270 mode 271 = EFFECT3; 272 break; 273 case 4: 274 mode = EFFECT4; 275 break; 276 277 } 278} 279 280void time_set() 281{ 282 EEPROM.write(0x00,230); // 辉光管颜色值 283 284 color_number = 230; 285 make_color(&rgb[0],color_number); 286 for(unsigned 287 char i=1;i<6;i++){ 288 rgb[i] = rgb[0]; 289 } 290 //power(); 291} 292
light.cpp
c_cpp
1#include "Adafruit_NeoPixel.h" 2#include "light.h" 3#include "RX8025.h" 4 5extern 6 unsigned char _t[6]; 7 8Adafruit_NeoPixel light[6] = {Adafruit_NeoPixel(10, 9 13, NEO_GRB + NEO_KHZ800), 10 Adafruit_NeoPixel(10, 11 12, NEO_GRB + NEO_KHZ800), 12 Adafruit_NeoPixel(10, 13 11, NEO_GRB + NEO_KHZ800), 14 Adafruit_NeoPixel(10, 15 10, NEO_GRB + NEO_KHZ800), 16 Adafruit_NeoPixel(10, 17 9 , NEO_GRB + NEO_KHZ800), 18 Adafruit_NeoPixel(10, 19 8 , NEO_GRB + NEO_KHZ800)}; 20 21color rgb[6]; 22 23void light_init(){ 24 unsigned 25 char i; 26 for(i=0;i<6;i++)light[i].begin(); 27} 28 29void poeron_effect()// 30{ 31 32 #define TTT 80 33 #define WHITE 100 34 unsigned char i,j,k; 35 for(k=0;k<2;k++) 36 37 { 38 for(i=0;i<6;i++) //i 39 { 40 RX8025_READ(_t); 41 light_wirte(_t,rgb); 42 43 for(j=0;j<_t[i];j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); 44 //j 45 light[i].setPixelColor(_t[i], light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 46 47 for(j=_t[i]+1;j<10;j++)light[i].setPixelColor(j, light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); 48 49 light[i].show(); 50 for(j=0;j<10;j++)light[i].setPixelColor(j, light[i].Color(0,0,0)); 51 52 delay(TTT); 53 } 54 for(i=5;i!=255;i--) //i 55 { 56 RX8025_READ(_t); 57 58 light_wirte(_t,rgb); 59 for(j=0;j<_t[i];j++)light[i].setPixelColor(j, 60 light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); //j 61 light[i].setPixelColor(_t[i], 62 light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 63 for(j=_t[i]+1;j<10;j++)light[i].setPixelColor(j, 64 light[i].Color((rgb[i].r>>2)+50,(rgb[i].g>>2)+50,(rgb[i].b>>2)+50)); 65 light[i].show(); 66 67 for(j=0;j<10;j++)light[i].setPixelColor(j, light[i].Color(0,0,0)); 68 delay(TTT); 69 70 } 71 } 72} 73 74void effect4() 75{ 76 static unsigned char n=0,col=0; 77 78 unsigned char temp,temp1; 79 80 light[temp=n/10].setPixelColor(temp1=n%10, 81 light[n/10].Color(rgb[temp].r,rgb[temp].g,rgb[temp].b)); 82 light[temp=5-temp].setPixelColor(10-temp1, 83 light[n/10].Color(rgb[temp].r,rgb[temp].g,rgb[temp].b)); 84 for(unsigned char 85 i=0;i<6;i++)light[i].show(); 86 for(unsigned char i=0;i<6;i++) 87 for(unsigned 88 char j=0;j<10;j++) 89 light[i].setPixelColor(j, light[i].Color(0,0,0)); 90 91 n++; 92 if(n==60) 93 { 94 n=0; 95 make_color(&rgb[0],col+=20); 96 97 for(unsigned char i=1;i<6;i++){ 98 rgb[i] = rgb[0]; 99 } 100 } 101} 102 103void 104 light_wirte(unsigned char* number,color* rgb){ 105 unsigned char i; 106 for(i=0;i<6;i++) 107 108 light[i].setPixelColor(*(number + i), light[i].Color(rgb[i].r,rgb[i].g,rgb[i].b)); 109 110 for(i=0;i<6;i++) 111 light[i].show(); 112 for(i=0;i<6;i++) 113 light[i].setPixelColor(*(number 114 + i), light[0].Color(0,0,0)); 115} 116 117/*rgb*/ 118void make_color(color *p,unsigned 119 char c_n) 120{ 121 unsigned char WheelPos; 122 color rgb_temp; 123 124 WheelPos=255-(((256/8)+c_n)&255); 125 if(WheelPos < 85) 126 { 127 rgb_temp.r=255 - WheelPos * 3;rgb_temp.g=0;rgb_temp.b=WheelPos * 3; 128 *p 129 = rgb_temp; 130 return; 131 } 132 if(WheelPos < 170) 133 134 { WheelPos -= 85;rgb_temp.r=0;rgb_temp.g=WheelPos * 3;rgb_temp.b=255 - 135 WheelPos * 3; 136 *p = rgb_temp; 137 return; 138 } 139 140 WheelPos -= 170;rgb_temp.r=WheelPos * 3;rgb_temp.g=255 - WheelPos * 3;rgb_temp.b=0; 141 142 *p = rgb_temp; 143 return; 144} 145/**/ 146void wheel(color* p) 147{ 148 149 static unsigned char i=0; 150 unsigned char j,WheelPos; 151 color rgbxxx; 152 153 for(j=0;j<6;j++) 154 { 155 WheelPos=255-(((j*256/8)+i)&255); 156 if(WheelPos 157 < 85) 158 { rgbxxx.r=255 - WheelPos * 3;rgbxxx.g=0;rgbxxx.b=WheelPos * 159 3; 160 *(p+j)=rgbxxx; 161 continue; 162 } 163 if(WheelPos 164 < 170) 165 { WheelPos -= 85;rgbxxx.r=0;rgbxxx.g=WheelPos * 3;rgbxxx.b=255 166 - WheelPos * 3; 167 *(p+j)=rgbxxx; 168 continue; 169 } 170 171 WheelPos -= 170;rgbxxx.r=WheelPos * 3;rgbxxx.g=255 - WheelPos * 3;rgbxxx.b=0; 172 173 *(p+j)=rgbxxx; 174 } 175 i++; 176} 177
Adafruit_NeoPixel.h
c_cpp
1/*-------------------------------------------------------------------- 2 3 This file is part of the Adafruit NeoPixel library. 4 5 NeoPixel is free 6 software: you can redistribute it and/or modify 7 it under the terms of the GNU 8 Lesser General Public License as 9 published by the Free Software Foundation, 10 either version 3 of 11 the License, or (at your option) any later version. 12 13 14 NeoPixel is distributed in the hope that it will be useful, 15 but WITHOUT ANY 16 WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR 18 A PARTICULAR PURPOSE. See the 19 GNU Lesser General Public License for more details. 20 21 22 You should have received a copy of the GNU Lesser General Public 23 License 24 along with NeoPixel. If not, see 25 <http://www.gnu.org/licenses/>. 26 --------------------------------------------------------------------*/ 27 28#ifndef 29 ADAFRUIT_NEOPIXEL_H 30#define ADAFRUIT_NEOPIXEL_H 31 32#if (ARDUINO >= 100) 33 34 #include <Arduino.h> 35#else 36 #include <WProgram.h> 37 #include <pins_arduino.h> 38#endif 39 40// 41 The order of primary colors in the NeoPixel data stream can vary 42// among device 43 types, manufacturers and even different revisions of 44// the same item. The third 45 parameter to the Adafruit_NeoPixel 46// constructor encodes the per-pixel byte 47 offsets of the red, green 48// and blue primaries (plus white, if present) in the 49 data stream -- 50// the following #defines provide an easier-to-use named version 51 for 52// each permutation. e.g. NEO_GRB indicates a NeoPixel-compatible 53// 54 device expecting three bytes per pixel, with the first byte 55// containing the 56 green value, second containing red and third 57// containing blue. The in-memory 58 representation of a chain of 59// NeoPixels is the same as the data-stream order; 60 no re-ordering of 61// bytes is required when issuing data to the chain. 62 63// 64 Bits 5,4 of this value are the offset (0-3) from the first byte of 65// a pixel 66 to the location of the red color byte. Bits 3,2 are the 67// green offset and 68 1,0 are the blue offset. If it is an RGBW-type 69// device (supporting a white 70 primary in addition to R,G,B), bits 7,6 71// are the offset to the white byte...otherwise, 72 bits 7,6 are set to 73// the same value as 5,4 (red) to indicate an RGB (not RGBW) 74 device. 75// i.e. binary representation: 76// 0bWWRRGGBB for RGBW devices 77// 78 0bRRRRGGBB for RGB 79 80// RGB NeoPixel permutations; white and red offsets are 81 always same 82// Offset: W R G B 83#define 84 NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2)) 85#define NEO_RBG ((0 << 6) | 86 (0 << 4) | (2 << 2) | (1)) 87#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | 88 (2)) 89#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1)) 90#define NEO_BRG 91 ((1 << 6) | (1 << 4) | (2 << 2) | (0)) 92#define NEO_BGR ((2 << 6) | (2 << 4) 93 | (1 << 2) | (0)) 94 95// RGBW NeoPixel permutations; all 4 offsets are distinct 96// 97 Offset: W R G B 98#define NEO_WRGB ((0 << 6) 99 | (1 << 4) | (2 << 2) | (3)) 100#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) 101 | (2)) 102#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3)) 103#define NEO_WGBR 104 ((0 << 6) | (3 << 4) | (1 << 2) | (2)) 105#define NEO_WBRG ((0 << 6) | (2 << 4) 106 | (3 << 2) | (1)) 107#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1)) 108 109#define 110 NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3)) 111#define NEO_RWBG ((1 << 6) | 112 (0 << 4) | (3 << 2) | (2)) 113#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | 114 (3)) 115#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2)) 116#define NEO_RBWG 117 ((2 << 6) | (0 << 4) | (3 << 2) | (1)) 118#define NEO_RBGW ((3 << 6) | (0 << 4) 119 | (2 << 2) | (1)) 120 121#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3)) 122#define 123 NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2)) 124#define NEO_GRWB ((2 << 6) | 125 (1 << 4) | (0 << 2) | (3)) 126#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | 127 (2)) 128#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1)) 129#define NEO_GBRW 130 ((3 << 6) | (2 << 4) | (0 << 2) | (1)) 131 132#define NEO_BWRG ((1 << 6) | (2 << 133 4) | (3 << 2) | (0)) 134#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0)) 135#define 136 NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0)) 137#define NEO_BRGW ((3 << 6) | 138 (1 << 4) | (2 << 2) | (0)) 139#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | 140 (0)) 141#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0)) 142 143// Add NEO_KHZ400 144 to the color order value to indicate a 400 KHz 145// device. All but the earliest 146 v1 NeoPixels expect an 800 KHz data 147// stream, this is the default if unspecified. 148 Because flash space 149// is very limited on ATtiny devices (e.g. Trinket, Gemma), 150 v1 151// NeoPixels aren't handled by default on those chips, though it can 152// 153 be enabled by removing the ifndef/endif below -- but code will be 154// bigger. 155 Conversely, can disable the NEO_KHZ400 line on other MCUs 156// to remove v1 support 157 and save a little space. 158 159#define NEO_KHZ800 0x0000 // 800 KHz datastream 160#ifndef 161 __AVR_ATtiny85__ 162#define NEO_KHZ400 0x0100 // 400 KHz datastream 163#endif 164 165// 166 If 400 KHz support is enabled, the third parameter to the constructor 167// requires 168 a 16-bit value (in order to select 400 vs 800 KHz speed). 169// If only 800 KHz 170 is enabled (as is default on ATtiny), an 8-bit value 171// is sufficient to encode 172 pixel color order, saving some space. 173 174#ifdef NEO_KHZ400 175typedef uint16_t 176 neoPixelType; 177#else 178typedef uint8_t neoPixelType; 179#endif 180 181class 182 Adafruit_NeoPixel { 183 184 public: 185 186 // Constructor: number of LEDs, pin 187 number, LED type 188 Adafruit_NeoPixel(uint16_t n, uint8_t p=6, neoPixelType t=NEO_GRB 189 + NEO_KHZ800); 190 Adafruit_NeoPixel(void); 191 ~Adafruit_NeoPixel(); 192 193 194 void 195 begin(void), 196 show(void), 197 setPin(uint8_t p), 198 setPixelColor(uint16_t 199 n, uint8_t r, uint8_t g, uint8_t b), 200 setPixelColor(uint16_t n, uint8_t r, 201 uint8_t g, uint8_t b, uint8_t w), 202 setPixelColor(uint16_t n, uint32_t c), 203 204 setBrightness(uint8_t), 205 clear(), 206 updateLength(uint16_t n), 207 208 updateType(neoPixelType t); 209 uint8_t 210 *getPixels(void) const, 211 getBrightness(void) 212 const; 213 int8_t 214 getPin(void) { return pin; }; 215 uint16_t 216 numPixels(void) 217 const; 218 static uint32_t 219 Color(uint8_t r, uint8_t g, uint8_t b), 220 Color(uint8_t 221 r, uint8_t g, uint8_t b, uint8_t w); 222 uint32_t 223 getPixelColor(uint16_t 224 n) const; 225 inline bool 226 canShow(void) { return (micros() - endTime) >= 227 300L; } 228 229 protected: 230 231 boolean 232#ifdef NEO_KHZ400 // If 400 KHz 233 NeoPixel support enabled... 234 is800KHz, // ...true if 800 KHz pixels 235#endif 236 237 begun; // true if begin() previously called 238 uint16_t 239 numLEDs, 240 // Number of RGB LEDs in strip 241 numBytes; // Size of 'pixels' 242 buffer below (3 or 4 bytes/pixel) 243 int8_t 244 pin; // Output pin 245 number (-1 if not yet set) 246 uint8_t 247 brightness, 248 *pixels, // 249 Holds LED color values (3 or 4 bytes each) 250 rOffset, // Index of red 251 byte within each 3- or 4-byte pixel 252 gOffset, // Index of green byte 253 254 bOffset, // Index of blue byte 255 wOffset; // Index of white 256 byte (same as rOffset if no white) 257 uint32_t 258 endTime; // Latch 259 timing reference 260#ifdef __AVR__ 261 volatile uint8_t 262 *port; // 263 Output PORT register 264 uint8_t 265 pinMask; // Output PORT bitmask 266#endif 267}; 268 269#endif 270 // ADAFRUIT_NEOPIXEL_H 271
Adafruit_NeoPixel.cpp
c_cpp
1/*------------------------------------------------------------------------- 2 3 Arduino library to control a wide variety of WS2811- and WS2812-based RGB 4 5 LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips. 6 Currently 7 handles 400 and 800 KHz bitstreams on 8, 12 and 16 MHz ATmega 8 MCUs, with LEDs 9 wired for various color orders. Handles most output pins 10 (possible exception 11 with upper PORT registers on the Arduino Mega). 12 13 Written by Phil Burgess 14 / Paint Your Dragon for Adafruit Industries, 15 contributions by PJRC, Michael 16 Miller and other members of the open 17 source community. 18 19 Adafruit invests 20 time and resources providing this open source code, 21 please support Adafruit 22 and open-source hardware by purchasing products 23 from Adafruit! 24 25 ------------------------------------------------------------------------- 26 27 This file is part of the Adafruit NeoPixel library. 28 29 NeoPixel is free 30 software: you can redistribute it and/or modify 31 it under the terms of the GNU 32 Lesser General Public License as 33 published by the Free Software Foundation, 34 either version 3 of 35 the License, or (at your option) any later version. 36 37 38 NeoPixel is distributed in the hope that it will be useful, 39 but WITHOUT ANY 40 WARRANTY; without even the implied warranty of 41 MERCHANTABILITY or FITNESS FOR 42 A PARTICULAR PURPOSE. See the 43 GNU Lesser General Public License for more details. 44 45 46 You should have received a copy of the GNU Lesser General Public 47 License 48 along with NeoPixel. If not, see 49 <http://www.gnu.org/licenses/>. 50 -------------------------------------------------------------------------*/ 51 52#include 53 "Adafruit_NeoPixel.h" 54 55#if defined(NRF52) 56#include "nrf.h" 57 58// 59 Interrupt is only disabled if there is no PWM device available 60// Note: Adafruit 61 Bluefruit nrf52 does not use this option 62//#define NRF52_DISABLE_INT 63#endif 64 65// 66 Constructor when length, pin and type are known at compile-time: 67Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t 68 n, uint8_t p, neoPixelType t) : 69 begun(false), brightness(0), pixels(NULL), 70 endTime(0) 71{ 72 updateType(t); 73 updateLength(n); 74 setPin(p); 75} 76 77// 78 via Michael Vogt/neophob: empty constructor is used when strand length 79// isn't 80 known at compile-time; situations where program config might be 81// read from 82 internal flash memory or an SD card, or arrive via serial 83// command. If using 84 this constructor, MUST follow up with updateType(), 85// updateLength(), etc. to 86 establish the strand type, length and pin number! 87Adafruit_NeoPixel::Adafruit_NeoPixel() 88 : 89#ifdef NEO_KHZ400 90 is800KHz(true), 91#endif 92 begun(false), numLEDs(0), 93 numBytes(0), pin(-1), brightness(0), pixels(NULL), 94 rOffset(1), gOffset(0), 95 bOffset(2), wOffset(1), endTime(0) 96{ 97} 98 99Adafruit_NeoPixel::~Adafruit_NeoPixel() 100 { 101 if(pixels) free(pixels); 102 if(pin >= 0) pinMode(pin, INPUT); 103} 104 105void 106 Adafruit_NeoPixel::begin(void) { 107 if(pin >= 0) { 108 pinMode(pin, OUTPUT); 109 110 digitalWrite(pin, LOW); 111 } 112 begun = true; 113 114} 115 116void Adafruit_NeoPixel::updateLength(uint16_t 117 n) { 118 if(pixels) free(pixels); // Free existing data (if any) 119 120 // Allocate 121 new data -- note: ALL PIXELS ARE CLEARED 122 numBytes = n * ((wOffset == rOffset) 123 ? 3 : 4); 124 if((pixels = (uint8_t *)malloc(numBytes))) { 125 memset(pixels, 126 0, numBytes); 127 numLEDs = n; 128 } else { 129 numLEDs = numBytes = 0; 130 131 } 132} 133 134void Adafruit_NeoPixel::updateType(neoPixelType t) { 135 boolean 136 oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW 137 138 wOffset 139 = (t >> 6) & 0b11; // See notes in header file 140 rOffset = (t >> 4) & 0b11; // 141 regarding R/G/B/W offsets 142 gOffset = (t >> 2) & 0b11; 143 bOffset = t & 144 0b11; 145#ifdef NEO_KHZ400 146 is800KHz = (t < 256); // 400 KHz flag is 1<<8 147#endif 148 149 150 // If bytes-per-pixel has changed (and pixel data was previously 151 // allocated), 152 re-allocate to new size. Will clear any data. 153 if(pixels) { 154 boolean 155 newThreeBytesPerPixel = (wOffset == rOffset); 156 if(newThreeBytesPerPixel != 157 oldThreeBytesPerPixel) updateLength(numLEDs); 158 } 159} 160 161#if defined(ESP8266) 162 163// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution 164extern 165 "C" void ICACHE_RAM_ATTR espShow( 166 uint8_t pin, uint8_t *pixels, uint32_t 167 numBytes, uint8_t type); 168#elif defined(ESP32) 169extern "C" void espShow( 170 171 uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t type); 172#endif // ESP8266 173 174void 175 Adafruit_NeoPixel::show(void) { 176 177 if(!pixels) return; 178 179 // Data latch 180 = 300+ microsecond pause in the output stream. Rather than 181 // put a delay 182 at the end of the function, the ending time is noted and 183 // the function will 184 simply hold off (if needed) on issuing the 185 // subsequent round of data until 186 the latch time has elapsed. This 187 // allows the mainline code to start generating 188 the next frame of data 189 // rather than stalling for the latch. 190 while(!canShow()); 191 192 // endTime is a private member (rather than global var) so that multiple 193 // 194 instances on different pins can be quickly issued in succession (each 195 // instance 196 doesn't delay the next). 197 198 // In order to make this code runtime-configurable 199 to work with any pin, 200 // SBI/CBI instructions are eschewed in favor of full 201 PORT writes via the 202 // OUT or ST instructions. It relies on two facts: that 203 peripheral 204 // functions (such as PWM) take precedence on output pins, so our 205 PORT- 206 // wide writes won't interfere, and that interrupts are globally disabled 207 208 // while data is being issued to the LEDs, so no other code will be 209 // accessing 210 the PORT. The code takes an initial 'snapshot' of the PORT 211 // state, computes 212 'pin high' and 'pin low' values, and writes these back 213 // to the PORT register 214 as needed. 215 216 // NRF52 may use PWM + DMA (if available), may not need to disable 217 interrupt 218#ifndef NRF52 219 noInterrupts(); // Need 100% focus on instruction 220 timing 221#endif 222 223#ifdef __AVR__ 224// AVR MCUs -- ATmega & ATtiny (no XMEGA) 225 --------------------------------- 226 227 volatile uint16_t 228 i = numBytes; 229 // Loop counter 230 volatile uint8_t 231 *ptr = pixels, // Pointer to next 232 byte 233 b = *ptr++, // Current byte value 234 hi, // PORT 235 w/output bit set high 236 lo; // PORT w/output bit set low 237 238 239 // Hand-tuned assembly code issues data to the LED drivers at a specific 240 // 241 rate. There's separate code for different CPU speeds (8, 12, 16 MHz) 242 // for 243 both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The 244 // datastream 245 timing for the LED drivers allows a little wiggle room each 246 // way (listed 247 in the datasheets), so the conditions for compiling each 248 // case are set up 249 for a range of frequencies rather than just the exact 250 // 8, 12 or 16 MHz values, 251 permitting use with some close-but-not-spot-on 252 // devices (e.g. 16.5 MHz DigiSpark). 253 The ranges were arrived at based 254 // on the datasheet figures and have not 255 been extensively tested outside 256 // the canonical 8/12/16 MHz speeds; there's 257 no guarantee these will work 258 // close to the extremes (or possibly they could 259 be pushed further). 260 // Keep in mind only one CPU speed case actually gets compiled; 261 the 262 // resulting program isn't as massive as it might look from source here. 263 264// 265 8 MHz(ish) AVR --------------------------------------------------------- 266#if 267 (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) 268 269#ifdef NEO_KHZ400 // 800 KHz 270 check needed only if 400 KHz support enabled 271 if(is800KHz) { 272#endif 273 274 275 volatile uint8_t n1, n2 = 0; // First, next bits out 276 277 // Squeezing 278 an 800 KHz stream out of an 8 MHz chip requires code 279 // specific to each 280 PORT register. 281 282 // 10 instruction clocks per bit: HHxxxxxLLL 283 // 284 OUT instructions: ^ ^ ^ (T=0,2,7) 285 286 // PORTD OUTPUT ---------------------------------------------------- 287 288#if 289 defined(PORTD) 290 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 291 if(port 292 == &PORTD) { 293 #endif // defined(PORTB/C/F) 294 295 hi = PORTD | pinMask; 296 297 lo = PORTD & ~pinMask; 298 n1 = lo; 299 if(b & 0x80) n1 = hi; 300 301 302 // Dirty trick: RJMPs proceeding to the next instruction are used 303 // 304 to delay two clock cycles in one instruction word (rather than 305 // using 306 two NOPs). This was necessary in order to squeeze the 307 // loop down to 308 exactly 64 words -- the maximum possible for a 309 // relative branch. 310 311 312 asm volatile( 313 "headD:" "\ 314\ " // Clk Pseudocode 315 316 // Bit 7: 317 "out %[port] , %[hi]" "\ 318\ " // 1 PORT 319 = hi 320 "mov %[n2] , %[lo]" "\ 321\ " // 1 n2 = lo 322 "out 323 %[port] , %[n1]" "\ 324\ " // 1 PORT = n1 325 "rjmp .+0" "\ 326\ " 327 // 2 nop nop 328 "sbrc %[byte] , 6" "\ 329\ " // 1-2 if(b & 330 0x40) 331 "mov %[n2] , %[hi]" "\ 332\ " // 0-1 n2 = hi 333 "out 334 %[port] , %[lo]" "\ 335\ " // 1 PORT = lo 336 "rjmp .+0" "\ 337\ " 338 // 2 nop nop 339 // Bit 6: 340 "out %[port] , %[hi]" "\ 341\ " 342 // 1 PORT = hi 343 "mov %[n1] , %[lo]" "\ 344\ " // 1 n1 = 345 lo 346 "out %[port] , %[n2]" "\ 347\ " // 1 PORT = n2 348 "rjmp 349 .+0" "\ 350\ " // 2 nop nop 351 "sbrc %[byte] , 5" 352 "\ 353\ " // 1-2 if(b & 0x20) 354 "mov %[n1] , %[hi]" "\ 355\ " 356 // 0-1 n1 = hi 357 "out %[port] , %[lo]" "\ 358\ " // 1 PORT 359 = lo 360 "rjmp .+0" "\ 361\ " // 2 nop nop 362 // 363 Bit 5: 364 "out %[port] , %[hi]" "\ 365\ " // 1 PORT = hi 366 "mov 367 %[n2] , %[lo]" "\ 368\ " // 1 n2 = lo 369 "out %[port] , 370 %[n1]" "\ 371\ " // 1 PORT = n1 372 "rjmp .+0" "\ 373\ " 374 // 2 nop nop 375 "sbrc %[byte] , 4" "\ 376\ " // 1-2 if(b & 377 0x10) 378 "mov %[n2] , %[hi]" "\ 379\ " // 0-1 n2 = hi 380 "out 381 %[port] , %[lo]" "\ 382\ " // 1 PORT = lo 383 "rjmp .+0" "\ 384\ " 385 // 2 nop nop 386 // Bit 4: 387 "out %[port] , %[hi]" "\ 388\ " 389 // 1 PORT = hi 390 "mov %[n1] , %[lo]" "\ 391\ " // 1 n1 = 392 lo 393 "out %[port] , %[n2]" "\ 394\ " // 1 PORT = n2 395 "rjmp 396 .+0" "\ 397\ " // 2 nop nop 398 "sbrc %[byte] , 3" 399 "\ 400\ " // 1-2 if(b & 0x08) 401 "mov %[n1] , %[hi]" "\ 402\ " 403 // 0-1 n1 = hi 404 "out %[port] , %[lo]" "\ 405\ " // 1 PORT 406 = lo 407 "rjmp .+0" "\ 408\ " // 2 nop nop 409 // 410 Bit 3: 411 "out %[port] , %[hi]" "\ 412\ " // 1 PORT = hi 413 "mov 414 %[n2] , %[lo]" "\ 415\ " // 1 n2 = lo 416 "out %[port] , 417 %[n1]" "\ 418\ " // 1 PORT = n1 419 "rjmp .+0" "\ 420\ " 421 // 2 nop nop 422 "sbrc %[byte] , 2" "\ 423\ " // 1-2 if(b & 424 0x04) 425 "mov %[n2] , %[hi]" "\ 426\ " // 0-1 n2 = hi 427 "out 428 %[port] , %[lo]" "\ 429\ " // 1 PORT = lo 430 "rjmp .+0" "\ 431\ " 432 // 2 nop nop 433 // Bit 2: 434 "out %[port] , %[hi]" "\ 435\ " 436 // 1 PORT = hi 437 "mov %[n1] , %[lo]" "\ 438\ " // 1 n1 = 439 lo 440 "out %[port] , %[n2]" "\ 441\ " // 1 PORT = n2 442 "rjmp 443 .+0" "\ 444\ " // 2 nop nop 445 "sbrc %[byte] , 1" 446 "\ 447\ " // 1-2 if(b & 0x02) 448 "mov %[n1] , %[hi]" "\ 449\ " 450 // 0-1 n1 = hi 451 "out %[port] , %[lo]" "\ 452\ " // 1 PORT 453 = lo 454 "rjmp .+0" "\ 455\ " // 2 nop nop 456 // 457 Bit 1: 458 "out %[port] , %[hi]" "\ 459\ " // 1 PORT = hi 460 "mov 461 %[n2] , %[lo]" "\ 462\ " // 1 n2 = lo 463 "out %[port] , 464 %[n1]" "\ 465\ " // 1 PORT = n1 466 "rjmp .+0" "\ 467\ " 468 // 2 nop nop 469 "sbrc %[byte] , 0" "\ 470\ " // 1-2 if(b & 471 0x01) 472 "mov %[n2] , %[hi]" "\ 473\ " // 0-1 n2 = hi 474 "out 475 %[port] , %[lo]" "\ 476\ " // 1 PORT = lo 477 "sbiw %[count], 478 1" "\ 479\ " // 2 i-- (don't act on Z flag yet) 480 // Bit 0: 481 482 "out %[port] , %[hi]" "\ 483\ " // 1 PORT = hi 484 "mov 485 %[n1] , %[lo]" "\ 486\ " // 1 n1 = lo 487 "out %[port] , 488 %[n2]" "\ 489\ " // 1 PORT = n2 490 "ld %[byte] , %a[ptr]+" "\ 491\ " 492 // 2 b = *ptr++ 493 "sbrc %[byte] , 7" "\ 494\ " // 1-2 if(b 495 & 0x80) 496 "mov %[n1] , %[hi]" "\ 497\ " // 0-1 n1 = hi 498 "out 499 %[port] , %[lo]" "\ 500\ " // 1 PORT = lo 501 "brne headD" "\ 502" 503 // 2 while(i) (Z flag set above) 504 : [byte] "+r" (b), 505 [n1] 506 "+r" (n1), 507 [n2] "+r" (n2), 508 [count] "+w" (i) 509 510 : [port] "I" (_SFR_IO_ADDR(PORTD)), 511 [ptr] "e" (ptr), 512 513 [hi] "r" (hi), 514 [lo] "r" (lo)); 515 516 #if defined(PORTB) 517 || defined(PORTC) || defined(PORTF) 518 } else // other PORT(s) 519 #endif // 520 defined(PORTB/C/F) 521#endif // defined(PORTD) 522 523 // PORTB OUTPUT ---------------------------------------------------- 524 525#if 526 defined(PORTB) 527 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 528 if(port 529 == &PORTB) { 530 #endif // defined(PORTD/C/F) 531 532 // Same as above, just 533 switched to PORTB and stripped of comments. 534 hi = PORTB | pinMask; 535 536 lo = PORTB & ~pinMask; 537 n1 = lo; 538 if(b & 0x80) n1 = hi; 539 540 541 asm volatile( 542 "headB:" "\ 543\ " 544 "out 545 %[port] , %[hi]" "\ 546\ " 547 "mov %[n2] , %[lo]" "\ 548\ " 549 550 "out %[port] , %[n1]" "\ 551\ " 552 "rjmp .+0" "\ 553\ " 554 555 "sbrc %[byte] , 6" "\ 556\ " 557 "mov %[n2] , %[hi]" 558 "\ 559\ " 560 "out %[port] , %[lo]" "\ 561\ " 562 "rjmp 563 .+0" "\ 564\ " 565 "out %[port] , %[hi]" "\ 566\ " 567 568 "mov %[n1] , %[lo]" "\ 569\ " 570 "out %[port] , %[n2]" 571 "\ 572\ " 573 "rjmp .+0" "\ 574\ " 575 "sbrc 576 %[byte] , 5" "\ 577\ " 578 "mov %[n1] , %[hi]" "\ 579\ " 580 581 "out %[port] , %[lo]" "\ 582\ " 583 "rjmp .+0" "\ 584\ " 585 586 "out %[port] , %[hi]" "\ 587\ " 588 "mov %[n2] , %[lo]" 589 "\ 590\ " 591 "out %[port] , %[n1]" "\ 592\ " 593 "rjmp 594 .+0" "\ 595\ " 596 "sbrc %[byte] , 4" "\ 597\ " 598 599 "mov %[n2] , %[hi]" "\ 600\ " 601 "out %[port] , %[lo]" 602 "\ 603\ " 604 "rjmp .+0" "\ 605\ " 606 "out 607 %[port] , %[hi]" "\ 608\ " 609 "mov %[n1] , %[lo]" "\ 610\ " 611 612 "out %[port] , %[n2]" "\ 613\ " 614 "rjmp .+0" "\ 615\ " 616 617 "sbrc %[byte] , 3" "\ 618\ " 619 "mov %[n1] , %[hi]" 620 "\ 621\ " 622 "out %[port] , %[lo]" "\ 623\ " 624 "rjmp 625 .+0" "\ 626\ " 627 "out %[port] , %[hi]" "\ 628\ " 629 630 "mov %[n2] , %[lo]" "\ 631\ " 632 "out %[port] , %[n1]" 633 "\ 634\ " 635 "rjmp .+0" "\ 636\ " 637 "sbrc 638 %[byte] , 2" "\ 639\ " 640 "mov %[n2] , %[hi]" "\ 641\ " 642 643 "out %[port] , %[lo]" "\ 644\ " 645 "rjmp .+0" "\ 646\ " 647 648 "out %[port] , %[hi]" "\ 649\ " 650 "mov %[n1] , %[lo]" 651 "\ 652\ " 653 "out %[port] , %[n2]" "\ 654\ " 655 "rjmp 656 .+0" "\ 657\ " 658 "sbrc %[byte] , 1" "\ 659\ " 660 661 "mov %[n1] , %[hi]" "\ 662\ " 663 "out %[port] , %[lo]" 664 "\ 665\ " 666 "rjmp .+0" "\ 667\ " 668 "out 669 %[port] , %[hi]" "\ 670\ " 671 "mov %[n2] , %[lo]" "\ 672\ " 673 674 "out %[port] , %[n1]" "\ 675\ " 676 "rjmp .+0" "\ 677\ " 678 679 "sbrc %[byte] , 0" "\ 680\ " 681 "mov %[n2] , %[hi]" 682 "\ 683\ " 684 "out %[port] , %[lo]" "\ 685\ " 686 "sbiw 687 %[count], 1" "\ 688\ " 689 "out %[port] , %[hi]" "\ 690\ " 691 692 "mov %[n1] , %[lo]" "\ 693\ " 694 "out %[port] , %[n2]" 695 "\ 696\ " 697 "ld %[byte] , %a[ptr]+" "\ 698\ " 699 "sbrc 700 %[byte] , 7" "\ 701\ " 702 "mov %[n1] , %[hi]" "\ 703\ " 704 705 "out %[port] , %[lo]" "\ 706\ " 707 "brne headB" "\ 708" 709 710 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 711 712 : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), 713 714 [lo] "r" (lo)); 715 716 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 717 718 } 719 #endif 720 #if defined(PORTC) || defined(PORTF) 721 else 722 #endif 723 // defined(PORTC/F) 724#endif // defined(PORTB) 725 726 // PORTC OUTPUT ---------------------------------------------------- 727 728#if 729 defined(PORTC) 730 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 731 if(port 732 == &PORTC) { 733 #endif // defined(PORTD/B/F) 734 735 // Same as above, just 736 switched to PORTC and stripped of comments. 737 hi = PORTC | pinMask; 738 739 lo = PORTC & ~pinMask; 740 n1 = lo; 741 if(b & 0x80) n1 = hi; 742 743 744 asm volatile( 745 "headC:" "\ 746\ " 747 "out 748 %[port] , %[hi]" "\ 749\ " 750 "mov %[n2] , %[lo]" "\ 751\ " 752 753 "out %[port] , %[n1]" "\ 754\ " 755 "rjmp .+0" "\ 756\ " 757 758 "sbrc %[byte] , 6" "\ 759\ " 760 "mov %[n2] , %[hi]" 761 "\ 762\ " 763 "out %[port] , %[lo]" "\ 764\ " 765 "rjmp 766 .+0" "\ 767\ " 768 "out %[port] , %[hi]" "\ 769\ " 770 771 "mov %[n1] , %[lo]" "\ 772\ " 773 "out %[port] , %[n2]" 774 "\ 775\ " 776 "rjmp .+0" "\ 777\ " 778 "sbrc 779 %[byte] , 5" "\ 780\ " 781 "mov %[n1] , %[hi]" "\ 782\ " 783 784 "out %[port] , %[lo]" "\ 785\ " 786 "rjmp .+0" "\ 787\ " 788 789 "out %[port] , %[hi]" "\ 790\ " 791 "mov %[n2] , %[lo]" 792 "\ 793\ " 794 "out %[port] , %[n1]" "\ 795\ " 796 "rjmp 797 .+0" "\ 798\ " 799 "sbrc %[byte] , 4" "\ 800\ " 801 802 "mov %[n2] , %[hi]" "\ 803\ " 804 "out %[port] , %[lo]" 805 "\ 806\ " 807 "rjmp .+0" "\ 808\ " 809 "out 810 %[port] , %[hi]" "\ 811\ " 812 "mov %[n1] , %[lo]" "\ 813\ " 814 815 "out %[port] , %[n2]" "\ 816\ " 817 "rjmp .+0" "\ 818\ " 819 820 "sbrc %[byte] , 3" "\ 821\ " 822 "mov %[n1] , %[hi]" 823 "\ 824\ " 825 "out %[port] , %[lo]" "\ 826\ " 827 "rjmp 828 .+0" "\ 829\ " 830 "out %[port] , %[hi]" "\ 831\ " 832 833 "mov %[n2] , %[lo]" "\ 834\ " 835 "out %[port] , %[n1]" 836 "\ 837\ " 838 "rjmp .+0" "\ 839\ " 840 "sbrc 841 %[byte] , 2" "\ 842\ " 843 "mov %[n2] , %[hi]" "\ 844\ " 845 846 "out %[port] , %[lo]" "\ 847\ " 848 "rjmp .+0" "\ 849\ " 850 851 "out %[port] , %[hi]" "\ 852\ " 853 "mov %[n1] , %[lo]" 854 "\ 855\ " 856 "out %[port] , %[n2]" "\ 857\ " 858 "rjmp 859 .+0" "\ 860\ " 861 "sbrc %[byte] , 1" "\ 862\ " 863 864 "mov %[n1] , %[hi]" "\ 865\ " 866 "out %[port] , %[lo]" 867 "\ 868\ " 869 "rjmp .+0" "\ 870\ " 871 "out 872 %[port] , %[hi]" "\ 873\ " 874 "mov %[n2] , %[lo]" "\ 875\ " 876 877 "out %[port] , %[n1]" "\ 878\ " 879 "rjmp .+0" "\ 880\ " 881 882 "sbrc %[byte] , 0" "\ 883\ " 884 "mov %[n2] , %[hi]" 885 "\ 886\ " 887 "out %[port] , %[lo]" "\ 888\ " 889 "sbiw 890 %[count], 1" "\ 891\ " 892 "out %[port] , %[hi]" "\ 893\ " 894 895 "mov %[n1] , %[lo]" "\ 896\ " 897 "out %[port] , %[n2]" 898 "\ 899\ " 900 "ld %[byte] , %a[ptr]+" "\ 901\ " 902 "sbrc 903 %[byte] , 7" "\ 904\ " 905 "mov %[n1] , %[hi]" "\ 906\ " 907 908 "out %[port] , %[lo]" "\ 909\ " 910 "brne headC" "\ 911" 912 913 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 914 915 : [port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi), 916 917 [lo] "r" (lo)); 918 919 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 920 921 } 922 #endif // defined(PORTD/B/F) 923 #if defined(PORTF) 924 else 925 #endif 926#endif 927 // defined(PORTC) 928 929 // PORTF OUTPUT ---------------------------------------------------- 930 931#if 932 defined(PORTF) 933 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 934 if(port 935 == &PORTF) { 936 #endif // defined(PORTD/B/C) 937 938 hi = PORTF | pinMask; 939 940 lo = PORTF & ~pinMask; 941 n1 = lo; 942 if(b & 0x80) n1 = hi; 943 944 945 asm volatile( 946 "headF:" "\ 947\ " 948 "out 949 %[port] , %[hi]" "\ 950\ " 951 "mov %[n2] , %[lo]" "\ 952\ " 953 954 "out %[port] , %[n1]" "\ 955\ " 956 "rjmp .+0" "\ 957\ " 958 959 "sbrc %[byte] , 6" "\ 960\ " 961 "mov %[n2] , %[hi]" 962 "\ 963\ " 964 "out %[port] , %[lo]" "\ 965\ " 966 "rjmp 967 .+0" "\ 968\ " 969 "out %[port] , %[hi]" "\ 970\ " 971 972 "mov %[n1] , %[lo]" "\ 973\ " 974 "out %[port] , %[n2]" 975 "\ 976\ " 977 "rjmp .+0" "\ 978\ " 979 "sbrc 980 %[byte] , 5" "\ 981\ " 982 "mov %[n1] , %[hi]" "\ 983\ " 984 985 "out %[port] , %[lo]" "\ 986\ " 987 "rjmp .+0" "\ 988\ " 989 990 "out %[port] , %[hi]" "\ 991\ " 992 "mov %[n2] , %[lo]" 993 "\ 994\ " 995 "out %[port] , %[n1]" "\ 996\ " 997 "rjmp 998 .+0" "\ 999\ " 1000 "sbrc %[byte] , 4" "\ 1001\ " 1002 1003 "mov %[n2] , %[hi]" "\ 1004\ " 1005 "out %[port] , %[lo]" 1006 "\ 1007\ " 1008 "rjmp .+0" "\ 1009\ " 1010 "out 1011 %[port] , %[hi]" "\ 1012\ " 1013 "mov %[n1] , %[lo]" "\ 1014\ " 1015 1016 "out %[port] , %[n2]" "\ 1017\ " 1018 "rjmp .+0" "\ 1019\ " 1020 1021 "sbrc %[byte] , 3" "\ 1022\ " 1023 "mov %[n1] , %[hi]" 1024 "\ 1025\ " 1026 "out %[port] , %[lo]" "\ 1027\ " 1028 "rjmp 1029 .+0" "\ 1030\ " 1031 "out %[port] , %[hi]" "\ 1032\ " 1033 1034 "mov %[n2] , %[lo]" "\ 1035\ " 1036 "out %[port] , %[n1]" 1037 "\ 1038\ " 1039 "rjmp .+0" "\ 1040\ " 1041 "sbrc 1042 %[byte] , 2" "\ 1043\ " 1044 "mov %[n2] , %[hi]" "\ 1045\ " 1046 1047 "out %[port] , %[lo]" "\ 1048\ " 1049 "rjmp .+0" "\ 1050\ " 1051 1052 "out %[port] , %[hi]" "\ 1053\ " 1054 "mov %[n1] , %[lo]" 1055 "\ 1056\ " 1057 "out %[port] , %[n2]" "\ 1058\ " 1059 "rjmp 1060 .+0" "\ 1061\ " 1062 "sbrc %[byte] , 1" "\ 1063\ " 1064 1065 "mov %[n1] , %[hi]" "\ 1066\ " 1067 "out %[port] , %[lo]" 1068 "\ 1069\ " 1070 "rjmp .+0" "\ 1071\ " 1072 "out 1073 %[port] , %[hi]" "\ 1074\ " 1075 "mov %[n2] , %[lo]" "\ 1076\ " 1077 1078 "out %[port] , %[n1]" "\ 1079\ " 1080 "rjmp .+0" "\ 1081\ " 1082 1083 "sbrc %[byte] , 0" "\ 1084\ " 1085 "mov %[n2] , %[hi]" 1086 "\ 1087\ " 1088 "out %[port] , %[lo]" "\ 1089\ " 1090 "sbiw 1091 %[count], 1" "\ 1092\ " 1093 "out %[port] , %[hi]" "\ 1094\ " 1095 1096 "mov %[n1] , %[lo]" "\ 1097\ " 1098 "out %[port] , %[n2]" 1099 "\ 1100\ " 1101 "ld %[byte] , %a[ptr]+" "\ 1102\ " 1103 "sbrc 1104 %[byte] , 7" "\ 1105\ " 1106 "mov %[n1] , %[hi]" "\ 1107\ " 1108 1109 "out %[port] , %[lo]" "\ 1110\ " 1111 "brne headF" "\ 1112" 1113 1114 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) 1115 1116 : [port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi), 1117 1118 [lo] "r" (lo)); 1119 1120 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 1121 1122 } 1123 #endif // defined(PORTD/B/C) 1124#endif // defined(PORTF) 1125 1126#ifdef 1127 NEO_KHZ400 1128 } else { // end 800 KHz, do 400 KHz 1129 1130 // Timing is more 1131 relaxed; unrolling the inner loop for each bit is 1132 // not necessary. Still 1133 using the peculiar RJMPs as 2X NOPs, not out 1134 // of need but just to trim 1135 the code size down a little. 1136 // This 400-KHz-datastream-on-8-MHz-CPU code 1137 is not quite identical 1138 // to the 800-on-16 code later -- the hi/lo timing 1139 between WS2811 and 1140 // WS2812 is not simply a 2:1 scale! 1141 1142 // 20 1143 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL 1144 // ST instructions: ^ 1145 ^ ^ (T=0,4,10) 1146 1147 volatile uint8_t next, bit; 1148 1149 hi 1150 = *port | pinMask; 1151 lo = *port & ~pinMask; 1152 next = lo; 1153 bit 1154 = 8; 1155 1156 asm volatile( 1157 "head20:" "\ 1158\ " 1159 // Clk Pseudocode (T = 0) 1160 "st %a[port], %[hi]" "\ 1161\ " // 1162 2 PORT = hi (T = 2) 1163 "sbrc %[byte] , 7" "\ 1164\ " // 1-2 1165 if(b & 128) 1166 "mov %[next], %[hi]" "\ 1167\ " // 0-1 next = hi 1168 (T = 4) 1169 "st %a[port], %[next]" "\ 1170\ " // 2 PORT = next 1171 (T = 6) 1172 "mov %[next] , %[lo]" "\ 1173\ " // 1 next = lo (T 1174 = 7) 1175 "dec %[bit]" "\ 1176\ " // 1 bit-- (T = 1177 8) 1178 "breq nextbyte20" "\ 1179\ " // 1-2 if(bit == 0) 1180 "rol 1181 %[byte]" "\ 1182\ " // 1 b <<= 1 (T = 10) 1183 "st %a[port], 1184 %[lo]" "\ 1185\ " // 2 PORT = lo (T = 12) 1186 "rjmp .+0" "\ 1187\ " 1188 // 2 nop nop (T = 14) 1189 "rjmp .+0" "\ 1190\ " // 1191 2 nop nop (T = 16) 1192 "rjmp .+0" "\ 1193\ " // 2 1194 nop nop (T = 18) 1195 "rjmp head20" "\ 1196\ " // 2 1197 -> head20 (next bit out) 1198 "nextbyte20:" "\ 1199\ " // 1200 (T = 10) 1201 "st %a[port], %[lo]" "\ 1202\ " // 1203 2 PORT = lo (T = 12) 1204 "nop" "\ 1205\ " // 1 1206 nop (T = 13) 1207 "ldi %[bit] , 8" "\ 1208\ " // 1 1209 bit = 8 (T = 14) 1210 "ld %[byte] , %a[ptr]+" "\ 1211\ " // 2 1212 b = *ptr++ (T = 16) 1213 "sbiw %[count], 1" "\ 1214\ " // 2 1215 i-- (T = 18) 1216 "brne head20" "\ 1217" // 2 if(i 1218 != 0) -> (next byte) 1219 : [port] "+e" (port), 1220 [byte] "+r" 1221 (b), 1222 [bit] "+r" (bit), 1223 [next] "+r" (next), 1224 [count] 1225 "+w" (i) 1226 : [hi] "r" (hi), 1227 [lo] "r" (lo), 1228 [ptr] 1229 "e" (ptr)); 1230 } 1231#endif // NEO_KHZ400 1232 1233// 12 MHz(ish) AVR -------------------------------------------------------- 1234#elif 1235 (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) 1236 1237#ifdef NEO_KHZ400 // 800 KHz 1238 check needed only if 400 KHz support enabled 1239 if(is800KHz) { 1240#endif 1241 1242 1243 // In the 12 MHz case, an optimized 800 KHz datastream (no dead time 1244 // 1245 between bytes) requires a PORT-specific loop similar to the 8 MHz 1246 // code 1247 (but a little more relaxed in this case). 1248 1249 // 15 instruction clocks per 1250 bit: HHHHxxxxxxLLLLL 1251 // OUT instructions: ^ ^ ^ (T=0,4,10) 1252 1253 1254 volatile uint8_t next; 1255 1256 // PORTD OUTPUT ---------------------------------------------------- 1257 1258#if 1259 defined(PORTD) 1260 #if defined(PORTB) || defined(PORTC) || defined(PORTF) 1261 if(port 1262 == &PORTD) { 1263 #endif // defined(PORTB/C/F) 1264 1265 hi = PORTD | pinMask; 1266 1267 lo = PORTD & ~pinMask; 1268 next = lo; 1269 if(b & 0x80) next = 1270 hi; 1271 1272 // Don't "optimize" the OUT calls into the bitTime subroutine; 1273 1274 // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs! 1275 asm 1276 volatile( 1277 "headD:" "\ 1278\ " // (T = 0) 1279 1280 "out %[port], %[hi]" "\ 1281\ " // (T = 1) 1282 "rcall 1283 bitTimeD" "\ 1284\ " // Bit 7 (T = 15) 1285 "out %[port], %[hi]" 1286 "\ 1287\ " 1288 "rcall bitTimeD" "\ 1289\ " // Bit 6 1290 "out 1291 %[port], %[hi]" "\ 1292\ " 1293 "rcall bitTimeD" "\ 1294\ " 1295 // Bit 5 1296 "out %[port], %[hi]" "\ 1297\ " 1298 "rcall bitTimeD" 1299 "\ 1300\ " // Bit 4 1301 "out %[port], %[hi]" "\ 1302\ " 1303 1304 "rcall bitTimeD" "\ 1305\ " // Bit 3 1306 "out %[port], 1307 %[hi]" "\ 1308\ " 1309 "rcall bitTimeD" "\ 1310\ " // Bit 2 1311 1312 "out %[port], %[hi]" "\ 1313\ " 1314 "rcall bitTimeD" "\ 1315\ " 1316 // Bit 1 1317 // Bit 0: 1318 "out %[port] , %[hi]" "\ 1319\ " 1320 // 1 PORT = hi (T = 1) 1321 "rjmp .+0" "\ 1322\ " 1323 // 2 nop nop (T = 3) 1324 "ld %[byte] , %a[ptr]+" "\ 1325\ " 1326 // 2 b = *ptr++ (T = 5) 1327 "out %[port] , %[next]" "\ 1328\ " 1329 // 1 PORT = next (T = 6) 1330 "mov %[next] , %[lo]" "\ 1331\ " 1332 // 1 next = lo (T = 7) 1333 "sbrc %[byte] , 7" "\ 1334\ " 1335 // 1-2 if(b & 0x80) (T = 8) 1336 "mov %[next] , %[hi]" "\ 1337\ " 1338 // 0-1 next = hi (T = 9) 1339 "nop" "\ 1340\ " 1341 // 1 (T = 10) 1342 "out %[port] , %[lo]" "\ 1343\ " 1344 // 1 PORT = lo (T = 11) 1345 "sbiw %[count], 1" "\ 1346\ " 1347 // 2 i-- (T = 13) 1348 "brne headD" "\ 1349\ " 1350 // 2 if(i != 0) -> (next byte) 1351 "rjmp doneD" "\ 1352\ " 1353 1354 "bitTimeD:" "\ 1355\ " // nop nop nop (T = 4) 1356 1357 "out %[port], %[next]" "\ 1358\ " // 1 PORT = next (T = 5) 1359 1360 "mov %[next], %[lo]" "\ 1361\ " // 1 next = lo (T = 6) 1362 1363 "rol %[byte]" "\ 1364\ " // 1 b <<= 1 (T = 7) 1365 1366 "sbrc %[byte], 7" "\ 1367\ " // 1-2 if(b & 0x80) (T = 8) 1368 1369 "mov %[next], %[hi]" "\ 1370\ " // 0-1 next = hi (T = 9) 1371 1372 "nop" "\ 1373\ " // 1 (T = 10) 1374 1375 "out %[port], %[lo]" "\ 1376\ " // 1 PORT = lo (T = 11) 1377 1378 "ret" "\ 1379\ " // 4 nop nop nop nop (T = 15) 1380 1381 "doneD:" "\ 1382" 1383 : [byte] "+r" (b), 1384 1385 [next] "+r" (next), 1386 [count] "+w" (i) 1387 : [port] 1388 "I" (_SFR_IO_ADDR(PORTD)), 1389 [ptr] "e" (ptr), 1390 [hi] 1391 "r" (hi), 1392 [lo] "r" (lo)); 1393 1394 #if defined(PORTB) || 1395 defined(PORTC) || defined(PORTF) 1396 } else // other PORT(s) 1397 #endif // defined(PORTB/C/F) 1398#endif 1399 // defined(PORTD) 1400 1401 // PORTB OUTPUT ---------------------------------------------------- 1402 1403#if 1404 defined(PORTB) 1405 #if defined(PORTD) || defined(PORTC) || defined(PORTF) 1406 if(port 1407 == &PORTB) { 1408 #endif // defined(PORTD/C/F) 1409 1410 hi = PORTB | pinMask; 1411 1412 lo = PORTB & ~pinMask; 1413 next = lo; 1414 if(b & 0x80) next = 1415 hi; 1416 1417 // Same as above, just set for PORTB & stripped of comments 1418 1419 asm volatile( 1420 "headB:" "\ 1421\ " 1422 "out 1423 %[port], %[hi]" "\ 1424\ " 1425 "rcall bitTimeB" "\ 1426\ " 1427 1428 "out %[port], %[hi]" "\ 1429\ " 1430 "rcall bitTimeB" "\ 1431\ " 1432 1433 "out %[port], %[hi]" "\ 1434\ " 1435 "rcall bitTimeB" "\ 1436\ " 1437 1438 "out %[port], %[hi]" "\ 1439\ " 1440 "rcall bitTimeB" "\ 1441\ " 1442 1443 "out %[port], %[hi]" "\ 1444\ " 1445 "rcall bitTimeB" "\ 1446\ " 1447 1448 "out %[port], %[hi]" "\ 1449\ " 1450 "rcall bitTimeB" "\ 1451\ " 1452 1453 "out %[port], %[hi]" "\ 1454\ " 1455 "rcall bitTimeB" "\ 1456\ " 1457 1458 "out %[port] , %[hi]" "\ 1459\ " 1460 "rjmp .+0" "\ 1461\ " 1462 1463 "ld %[byte] , %a[ptr]+" "\ 1464\ " 1465 "out %[port] , %[next]" 1466 "\ 1467\ " 1468 "mov %[next] , %[lo]" "\ 1469\ " 1470 "sbrc 1471 %[byte] , 7" "\ 1472\ " 1473 "mov %[next] , %[hi]" "\ 1474\ " 1475 1476 "nop" "\ 1477\ " 1478 "out %[port] , %[lo]" 1479 "\ 1480\ " 1481 "sbiw %[count], 1" "\ 1482\ " 1483 "brne 1484 headB" "\ 1485\ " 1486 "rjmp doneB" "\ 1487\ " 1488 1489 "bitTimeB:" "\ 1490\ " 1491 "out %[port], %[next]" 1492 "\ 1493\ " 1494 "mov %[next], %[lo]" "\ 1495\ " 1496 "rol 1497 %[byte]" "\ 1498\ " 1499 "sbrc %[byte], 7" "\ 1500\ " 1501 1502 "mov %[next], %[hi]" "\ 1503\ " 1504 "nop" "\ 1505\ " 1506 1507 "out %[port], %[lo]" "\ 1508\ " 1509 "ret" "\ 1510\ " 1511 1512 "doneB:" "\ 1513" 1514 : [byte] "+r" (b), [next] 1515 "+r" (next), [count] "+w" (i) 1516 : [port] "I" (_SFR_IO_ADDR(PORTB)), 1517 [ptr] "e" (ptr), [hi] "r" (hi), 1518 [lo] "r" (lo)); 1519 1520 #if defined(PORTD) 1521 || defined(PORTC) || defined(PORTF) 1522 } 1523 #endif 1524 #if defined(PORTC) || 1525 defined(PORTF) 1526 else 1527 #endif // defined(PORTC/F) 1528#endif // defined(PORTB) 1529 1530 1531 // PORTC OUTPUT ---------------------------------------------------- 1532 1533#if 1534 defined(PORTC) 1535 #if defined(PORTD) || defined(PORTB) || defined(PORTF) 1536 if(port 1537 == &PORTC) { 1538 #endif // defined(PORTD/B/F) 1539 1540 hi = PORTC | pinMask; 1541 1542 lo = PORTC & ~pinMask; 1543 next = lo; 1544 if(b & 0x80) next = 1545 hi; 1546 1547 // Same as above, just set for PORTC & stripped of comments 1548 1549 asm volatile( 1550 "headC:" "\ 1551\ " 1552 "out 1553 %[port], %[hi]" "\ 1554\ " 1555 "rcall bitTimeC" "\ 1556\ " 1557 1558 "out %[port], %[hi]" "\ 1559\ " 1560 "rcall bitTimeC" "\ 1561\ " 1562 1563 "out %[port], %[hi]" "\ 1564\ " 1565 "rcall bitTimeC" "\ 1566\ " 1567 1568 "out %[port], %[hi]" "\ 1569\ " 1570 "rcall bitTimeC" "\ 1571\ " 1572 1573 "out %[port], %[hi]" "\ 1574\ " 1575 "rcall bitTimeC" "\ 1576\ " 1577 1578 "out %[port], %[hi]" "\ 1579\ " 1580 "rcall bitTimeC" "\ 1581\ " 1582 1583 "out %[port], %[hi]" "\ 1584\ " 1585 "rcall bitTimeC" "\ 1586\ " 1587 1588 "out %[port] , %[hi]" "\ 1589\ " 1590 "rjmp .+0" "\ 1591\ " 1592 1593 "ld %[byte] , %a[ptr]+" "\ 1594\ " 1595 "out %[port] , %[next]" 1596 "\ 1597\ " 1598 "mov %[next] , %[lo]" "\ 1599\ " 1600 "sbrc 1601 %[byte] , 7" "\ 1602\ " 1603 "mov %[next] , %[hi]" "\ 1604\ " 1605 1606 "nop" "\ 1607\ " 1608 "out %[port] , %[lo]" 1609 "\ 1610\ " 1611 "sbiw %[count], 1" "\ 1612\ " 1613 "brne 1614 headC" "\ 1615\ " 1616 "rjmp doneC" "\ 1617\ " 1618 1619 "bitTimeC:" "\ 1620\ " 1621 "out %[port], %[next]" 1622 "\ 1623\ " 1624 "mov %[next], %[lo]" "\ 1625\ " 1626 "rol 1627 %[byte]" "\ 1628\ " 1629 "sbrc %[byte], 7" "\ 1630\ " 1631 1632 "mov %[next], %[hi]" "\ 1633\ " 1634 "nop" "\ 1635\ " 1636 1637 "out %[port], %[lo]" "\ 1638\ " 1639 "ret" "\ 1640\ " 1641 1642 "doneC:" "\ 1643" 1644 : [byte] "+r" (b), [next] 1645 "+r" (next), [count] "+w" (i) 1646 : [port] "I" (_SFR_IO_ADDR(PORTC)), 1647 [ptr] "e" (ptr), [hi] "r" (hi), 1648 [lo] "r" (lo)); 1649 1650 #if defined(PORTD) 1651 || defined(PORTB) || defined(PORTF) 1652 } 1653 #endif // defined(PORTD/B/F) 1654 1655 #if defined(PORTF) 1656 else 1657 #endif 1658#endif // defined(PORTC) 1659 1660 // 1661 PORTF OUTPUT ---------------------------------------------------- 1662 1663#if defined(PORTF) 1664 1665 #if defined(PORTD) || defined(PORTB) || defined(PORTC) 1666 if(port == &PORTF) 1667 { 1668 #endif // defined(PORTD/B/C) 1669 1670 hi = PORTF | pinMask; 1671 lo 1672 = PORTF & ~pinMask; 1673 next = lo; 1674 if(b & 0x80) next = hi; 1675 1676 1677 // Same as above, just set for PORTF & stripped of comments 1678 asm volatile( 1679 1680 "headF:" "\ 1681\ " 1682 "out %[port], %[hi]" 1683 "\ 1684\ " 1685 "rcall bitTimeC" "\ 1686\ " 1687 "out 1688 %[port], %[hi]" "\ 1689\ " 1690 "rcall bitTimeC" "\ 1691\ " 1692 1693 "out %[port], %[hi]" "\ 1694\ " 1695 "rcall bitTimeC" "\ 1696\ " 1697 1698 "out %[port], %[hi]" "\ 1699\ " 1700 "rcall bitTimeC" "\ 1701\ " 1702 1703 "out %[port], %[hi]" "\ 1704\ " 1705 "rcall bitTimeC" "\ 1706\ " 1707 1708 "out %[port], %[hi]" "\ 1709\ " 1710 "rcall bitTimeC" "\ 1711\ " 1712 1713 "out %[port], %[hi]" "\ 1714\ " 1715 "rcall bitTimeC" "\ 1716\ " 1717 1718 "out %[port] , %[hi]" "\ 1719\ " 1720 "rjmp .+0" "\ 1721\ " 1722 1723 "ld %[byte] , %a[ptr]+" "\ 1724\ " 1725 "out %[port] , %[next]" 1726 "\ 1727\ " 1728 "mov %[next] , %[lo]" "\ 1729\ " 1730 "sbrc 1731 %[byte] , 7" "\ 1732\ " 1733 "mov %[next] , %[hi]" "\ 1734\ " 1735 1736 "nop" "\ 1737\ " 1738 "out %[port] , %[lo]" 1739 "\ 1740\ " 1741 "sbiw %[count], 1" "\ 1742\ " 1743 "brne 1744 headF" "\ 1745\ " 1746 "rjmp doneC" "\ 1747\ " 1748 1749 "bitTimeC:" "\ 1750\ " 1751 "out %[port], %[next]" 1752 "\ 1753\ " 1754 "mov %[next], %[lo]" "\ 1755\ " 1756 "rol 1757 %[byte]" "\ 1758\ " 1759 "sbrc %[byte], 7" "\ 1760\ " 1761 1762 "mov %[next], %[hi]" "\ 1763\ " 1764 "nop" "\ 1765\ " 1766 1767 "out %[port], %[lo]" "\ 1768\ " 1769 "ret" "\ 1770\ " 1771 1772 "doneC:" "\ 1773" 1774 : [byte] "+r" (b), [next] 1775 "+r" (next), [count] "+w" (i) 1776 : [port] "I" (_SFR_IO_ADDR(PORTF)), 1777 [ptr] "e" (ptr), [hi] "r" (hi), 1778 [lo] "r" (lo)); 1779 1780 #if defined(PORTD) 1781 || defined(PORTB) || defined(PORTC) 1782 } 1783 #endif // defined(PORTD/B/C) 1784#endif 1785 // defined(PORTF) 1786 1787#ifdef NEO_KHZ400 1788 } else { // 400 KHz 1789 1790 // 1791 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL 1792 // ST instructions: 1793 ^ ^ ^ (T=0,6,15) 1794 1795 volatile uint8_t next, 1796 bit; 1797 1798 hi = *port | pinMask; 1799 lo = *port & ~pinMask; 1800 next 1801 = lo; 1802 bit = 8; 1803 1804 asm volatile( 1805 "head30:" "\ 1806\ " 1807 // Clk Pseudocode (T = 0) 1808 "st %a[port], %[hi]" "\ 1809\ " // 1810 2 PORT = hi (T = 2) 1811 "sbrc %[byte] , 7" "\ 1812\ " // 1-2 1813 if(b & 128) 1814 "mov %[next], %[hi]" "\ 1815\ " // 0-1 next = hi 1816 (T = 4) 1817 "rjmp .+0" "\ 1818\ " // 2 nop nop (T 1819 = 6) 1820 "st %a[port], %[next]" "\ 1821\ " // 2 PORT = next (T = 1822 8) 1823 "rjmp .+0" "\ 1824\ " // 2 nop nop (T = 1825 10) 1826 "rjmp .+0" "\ 1827\ " // 2 nop nop (T = 12) 1828 1829 "rjmp .+0" "\ 1830\ " // 2 nop nop (T = 14) 1831 1832 "nop" "\ 1833\ " // 1 nop (T = 15) 1834 1835 "st %a[port], %[lo]" "\ 1836\ " // 2 PORT = lo (T = 17) 1837 1838 "rjmp .+0" "\ 1839\ " // 2 nop nop (T = 19) 1840 1841 "dec %[bit]" "\ 1842\ " // 1 bit-- (T = 20) 1843 1844 "breq nextbyte30" "\ 1845\ " // 1-2 if(bit == 0) 1846 "rol 1847 %[byte]" "\ 1848\ " // 1 b <<= 1 (T = 22) 1849 "rjmp 1850 .+0" "\ 1851\ " // 2 nop nop (T = 24) 1852 "rjmp .+0" 1853 "\ 1854\ " // 2 nop nop (T = 26) 1855 "rjmp .+0" 1856 "\ 1857\ " // 2 nop nop (T = 28) 1858 "rjmp head30" 1859 "\ 1860\ " // 2 -> head30 (next bit out) 1861 "nextbyte30:" 1862 "\ 1863\ " // (T = 22) 1864 "nop" "\ 1865\ " 1866 // 1 nop (T = 23) 1867 "ldi %[bit] , 8" "\ 1868\ " // 1869 1 bit = 8 (T = 24) 1870 "ld %[byte] , %a[ptr]+" "\ 1871\ " // 2 1872 b = *ptr++ (T = 26) 1873 "sbiw %[count], 1" "\ 1874\ " // 2 1875 i-- (T = 28) 1876 "brne head30" "\ 1877" // 1-2 1878 if(i != 0) -> (next byte) 1879 : [port] "+e" (port), 1880 [byte] 1881 "+r" (b), 1882 [bit] "+r" (bit), 1883 [next] "+r" (next), 1884 1885 [count] "+w" (i) 1886 : [hi] "r" (hi), 1887 [lo] "r" 1888 (lo), 1889 [ptr] "e" (ptr)); 1890 } 1891#endif // NEO_KHZ400 1892 1893// 1894 16 MHz(ish) AVR -------------------------------------------------------- 1895#elif 1896 (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) 1897 1898#ifdef NEO_KHZ400 // 800 KHz 1899 check needed only if 400 KHz support enabled 1900 if(is800KHz) { 1901#endif 1902 1903 1904 // WS2811 and WS2812 have different hi/lo duty cycles; this is 1905 // similar 1906 but NOT an exact copy of the prior 400-on-8 code. 1907 1908 // 20 inst. clocks 1909 per bit: HHHHHxxxxxxxxLLLLLLL 1910 // ST instructions: ^ ^ ^ 1911 (T=0,5,13) 1912 1913 volatile uint8_t next, bit; 1914 1915 hi = *port 1916 | pinMask; 1917 lo = *port & ~pinMask; 1918 next = lo; 1919 bit = 8; 1920 1921 1922 asm volatile( 1923 "head20:" "\ 1924\ " // Clk Pseudocode 1925 (T = 0) 1926 "st %a[port], %[hi]" "\ 1927\ " // 2 PORT = hi 1928 (T = 2) 1929 "sbrc %[byte], 7" "\ 1930\ " // 1-2 if(b & 128) 1931 1932 "mov %[next], %[hi]" "\ 1933\ " // 0-1 next = hi (T = 4) 1934 1935 "dec %[bit]" "\ 1936\ " // 1 bit-- (T = 5) 1937 1938 "st %a[port], %[next]" "\ 1939\ " // 2 PORT = next (T = 7) 1940 1941 "mov %[next] , %[lo]" "\ 1942\ " // 1 next = lo (T = 8) 1943 1944 "breq nextbyte20" "\ 1945\ " // 1-2 if(bit == 0) (from dec above) 1946 1947 "rol %[byte]" "\ 1948\ " // 1 b <<= 1 (T = 10) 1949 1950 "rjmp .+0" "\ 1951\ " // 2 nop nop (T = 12) 1952 1953 "nop" "\ 1954\ " // 1 nop (T = 13) 1955 1956 "st %a[port], %[lo]" "\ 1957\ " // 2 PORT = lo (T = 15) 1958 1959 "nop" "\ 1960\ " // 1 nop (T = 16) 1961 1962 "rjmp .+0" "\ 1963\ " // 2 nop nop (T = 18) 1964 1965 "rjmp head20" "\ 1966\ " // 2 -> head20 (next bit out) 1967 1968 "nextbyte20:" "\ 1969\ " // (T = 10) 1970 1971 "ldi %[bit] , 8" "\ 1972\ " // 1 bit = 8 (T = 11) 1973 1974 "ld %[byte] , %a[ptr]+" "\ 1975\ " // 2 b = *ptr++ (T = 13) 1976 1977 "st %a[port], %[lo]" "\ 1978\ " // 2 PORT = lo (T = 15) 1979 1980 "nop" "\ 1981\ " // 1 nop (T = 16) 1982 1983 "sbiw %[count], 1" "\ 1984\ " // 2 i-- (T = 18) 1985 1986 "brne head20" "\ 1987" // 2 if(i != 0) -> (next byte) 1988 1989 : [port] "+e" (port), 1990 [byte] "+r" (b), 1991 [bit] "+r" 1992 (bit), 1993 [next] "+r" (next), 1994 [count] "+w" (i) 1995 : 1996 [ptr] "e" (ptr), 1997 [hi] "r" (hi), 1998 [lo] "r" 1999 (lo)); 2000 2001#ifdef NEO_KHZ400 2002 } else { // 400 KHz 2003 2004 // The 400 KHz 2005 clock on 16 MHz MCU is the most 'relaxed' version. 2006 2007 // 40 inst. clocks 2008 per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL 2009 // ST instructions: ^ 2010 ^ ^ (T=0,8,20) 2011 2012 volatile uint8_t next, bit; 2013 2014 2015 hi = *port | pinMask; 2016 lo = *port & ~pinMask; 2017 next = lo; 2018 2019 bit = 8; 2020 2021 asm volatile( 2022 "head40:" "\ 2023\ " 2024 // Clk Pseudocode (T = 0) 2025 "st %a[port], %[hi]" "\ 2026\ " // 2027 2 PORT = hi (T = 2) 2028 "sbrc %[byte] , 7" "\ 2029\ " // 1-2 2030 if(b & 128) 2031 "mov %[next] , %[hi]" "\ 2032\ " // 0-1 next = hi 2033 (T = 4) 2034 "rjmp .+0" "\ 2035\ " // 2 nop nop (T 2036 = 6) 2037 "rjmp .+0" "\ 2038\ " // 2 nop nop (T = 2039 8) 2040 "st %a[port], %[next]" "\ 2041\ " // 2 PORT = next (T = 2042 10) 2043 "rjmp .+0" "\ 2044\ " // 2 nop nop (T = 12) 2045 2046 "rjmp .+0" "\ 2047\ " // 2 nop nop (T = 14) 2048 2049 "rjmp .+0" "\ 2050\ " // 2 nop nop (T = 16) 2051 2052 "rjmp .+0" "\ 2053\ " // 2 nop nop (T = 18) 2054 2055 "rjmp .+0" "\ 2056\ " // 2 nop nop (T = 20) 2057 2058 "st %a[port], %[lo]" "\ 2059\ " // 2 PORT = lo (T = 22) 2060 2061 "nop" "\ 2062\ " // 1 nop (T = 23) 2063 2064 "mov %[next] , %[lo]" "\ 2065\ " // 1 next = lo (T = 24) 2066 2067 "dec %[bit]" "\ 2068\ " // 1 bit-- (T = 25) 2069 2070 "breq nextbyte40" "\ 2071\ " // 1-2 if(bit == 0) 2072 "rol 2073 %[byte]" "\ 2074\ " // 1 b <<= 1 (T = 27) 2075 "nop" 2076 "\ 2077\ " // 1 nop (T = 28) 2078 "rjmp .+0" 2079 "\ 2080\ " // 2 nop nop (T = 30) 2081 "rjmp .+0" 2082 "\ 2083\ " // 2 nop nop (T = 32) 2084 "rjmp .+0" 2085 "\ 2086\ " // 2 nop nop (T = 34) 2087 "rjmp .+0" 2088 "\ 2089\ " // 2 nop nop (T = 36) 2090 "rjmp .+0" 2091 "\ 2092\ " // 2 nop nop (T = 38) 2093 "rjmp head40" 2094 "\ 2095\ " // 2 -> head40 (next bit out) 2096 "nextbyte40:" 2097 "\ 2098\ " // (T = 27) 2099 "ldi %[bit] , 2100 8" "\ 2101\ " // 1 bit = 8 (T = 28) 2102 "ld %[byte] , %a[ptr]+" 2103 "\ 2104\ " // 2 b = *ptr++ (T = 30) 2105 "rjmp .+0" "\ 2106\ " 2107 // 2 nop nop (T = 32) 2108 "st %a[port], %[lo]" "\ 2109\ " // 2110 2 PORT = lo (T = 34) 2111 "rjmp .+0" "\ 2112\ " // 2 2113 nop nop (T = 36) 2114 "sbiw %[count], 1" "\ 2115\ " // 2 2116 i-- (T = 38) 2117 "brne head40" "\ 2118" // 1-2 2119 if(i != 0) -> (next byte) 2120 : [port] "+e" (port), 2121 [byte] 2122 "+r" (b), 2123 [bit] "+r" (bit), 2124 [next] "+r" (next), 2125 2126 [count] "+w" (i) 2127 : [ptr] "e" (ptr), 2128 [hi] "r" 2129 (hi), 2130 [lo] "r" (lo)); 2131 } 2132#endif // NEO_KHZ400 2133 2134#else 2135 2136 #error "CPU SPEED NOT SUPPORTED" 2137#endif // end F_CPU ifdefs on __AVR__ 2138 2139// 2140 END AVR ---------------------------------------------------------------- 2141 2142 2143#elif 2144 defined(__arm__) 2145 2146// ARM MCUs -- Teensy 3.0, 3.1, LC, Arduino Due --------------------------- 2147 2148#if 2149 defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6 2150#define 2151 CYCLES_800_T0H (F_CPU / 4000000) 2152#define CYCLES_800_T1H (F_CPU / 1250000) 2153#define 2154 CYCLES_800 (F_CPU / 800000) 2155#define CYCLES_400_T0H (F_CPU / 2000000) 2156#define 2157 CYCLES_400_T1H (F_CPU / 833333) 2158#define CYCLES_400 (F_CPU / 400000) 2159 2160 2161 uint8_t *p = pixels, 2162 *end = p + numBytes, pix, 2163 mask; 2164 volatile uint8_t *set = portSetRegister(pin), 2165 *clr 2166 = portClearRegister(pin); 2167 uint32_t cyc; 2168 2169 ARM_DEMCR |= ARM_DEMCR_TRCENA; 2170 2171 ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; 2172 2173#ifdef NEO_KHZ400 // 800 KHz check 2174 needed only if 400 KHz support enabled 2175 if(is800KHz) { 2176#endif 2177 cyc 2178 = ARM_DWT_CYCCNT + CYCLES_800; 2179 while(p < end) { 2180 pix = *p++; 2181 2182 for(mask = 0x80; mask; mask >>= 1) { 2183 while(ARM_DWT_CYCCNT - cyc 2184 < CYCLES_800); 2185 cyc = ARM_DWT_CYCCNT; 2186 *set = 1; 2187 if(pix 2188 & mask) { 2189 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H); 2190 } 2191 else { 2192 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H); 2193 } 2194 2195 *clr = 1; 2196 } 2197 } 2198 while(ARM_DWT_CYCCNT - cyc < CYCLES_800); 2199#ifdef 2200 NEO_KHZ400 2201 } else { // 400 kHz bitstream 2202 cyc = ARM_DWT_CYCCNT + CYCLES_400; 2203 2204 while(p < end) { 2205 pix = *p++; 2206 for(mask = 0x80; mask; mask >>= 2207 1) { 2208 while(ARM_DWT_CYCCNT - cyc < CYCLES_400); 2209 cyc = ARM_DWT_CYCCNT; 2210 2211 *set = 1; 2212 if(pix & mask) { 2213 while(ARM_DWT_CYCCNT 2214 - cyc < CYCLES_400_T1H); 2215 } else { 2216 while(ARM_DWT_CYCCNT - 2217 cyc < CYCLES_400_T0H); 2218 } 2219 *clr = 1; 2220 } 2221 } 2222 2223 while(ARM_DWT_CYCCNT - cyc < CYCLES_400); 2224 } 2225#endif // NEO_KHZ400 2226 2227#elif 2228 defined(TEENSYDUINO) && defined(__MKL26Z64__) // Teensy-LC 2229 2230#if F_CPU == 48000000 2231 2232 uint8_t *p = pixels, 2233 pix, count, dly, 2234 bitmask 2235 = digitalPinToBitMask(pin); 2236 volatile uint8_t *reg = portSetRegister(pin); 2237 2238 uint32_t num = numBytes; 2239 asm volatile( 2240 "L%=_begin:" "\ 2241\ " 2242 "ldrb %[pix], 2243 [%[p], #0]" "\ 2244\ " 2245 "lsl %[pix], #24" "\ 2246\ " 2247 "movs %[count], 2248 #7" "\ 2249\ " 2250 "L%=_loop:" "\ 2251\ " 2252 "lsl %[pix], #1" "\ 2253\ " 2254 "bcs L%=_loop_one" "\ 2255\ " 2256 "L%=_loop_zero:" 2257 "strb %[bitmask], 2258 [%[reg], #0]" "\ 2259\ " 2260 "movs %[dly], #4" "\ 2261\ " 2262 "L%=_loop_delay_T0H:" "\ 2263\ " 2264 "sub %[dly], 2265 #1" "\ 2266\ " 2267 "bne L%=_loop_delay_T0H" "\ 2268\ " 2269 "strb %[bitmask], 2270 [%[reg], #4]" "\ 2271\ " 2272 "movs %[dly], #13" "\ 2273\ " 2274 "L%=_loop_delay_T0L:" "\ 2275\ " 2276 "sub %[dly], 2277 #1" "\ 2278\ " 2279 "bne L%=_loop_delay_T0L" "\ 2280\ " 2281 "b L%=_next" "\ 2282\ " 2283 "L%=_loop_one:" 2284 "strb %[bitmask], 2285 [%[reg], #0]" "\ 2286\ " 2287 "movs %[dly], #13" "\ 2288\ " 2289 "L%=_loop_delay_T1H:" "\ 2290\ " 2291 "sub %[dly], 2292 #1" "\ 2293\ " 2294 "bne L%=_loop_delay_T1H" "\ 2295\ " 2296 "strb %[bitmask], 2297 [%[reg], #4]" "\ 2298\ " 2299 "movs %[dly], #4" "\ 2300\ " 2301 "L%=_loop_delay_T1L:" "\ 2302\ " 2303 "sub %[dly], 2304 #1" "\ 2305\ " 2306 "bne L%=_loop_delay_T1L" "\ 2307\ " 2308 "nop" "\ 2309\ " 2310 "L%=_next:" "\ 2311\ " 2312 "sub %[count], 2313 #1" "\ 2314\ " 2315 "bne L%=_loop" "\ 2316\ " 2317 "lsl %[pix], 2318 #1" "\ 2319\ " 2320 "bcs L%=_last_one" "\ 2321\ " 2322 "L%=_last_zero:" 2323 "strb %[bitmask], 2324 [%[reg], #0]" "\ 2325\ " 2326 "movs %[dly], #4" "\ 2327\ " 2328 "L%=_last_delay_T0H:" "\ 2329\ " 2330 "sub %[dly], 2331 #1" "\ 2332\ " 2333 "bne L%=_last_delay_T0H" "\ 2334\ " 2335 "strb %[bitmask], 2336 [%[reg], #4]" "\ 2337\ " 2338 "movs %[dly], #10" "\ 2339\ " 2340 "L%=_last_delay_T0L:" "\ 2341\ " 2342 "sub %[dly], 2343 #1" "\ 2344\ " 2345 "bne L%=_last_delay_T0L" "\ 2346\ " 2347 "b L%=_repeat" "\ 2348\ " 2349 "L%=_last_one:" 2350 "strb %[bitmask], 2351 [%[reg], #0]" "\ 2352\ " 2353 "movs %[dly], #13" "\ 2354\ " 2355 "L%=_last_delay_T1H:" "\ 2356\ " 2357 "sub %[dly], 2358 #1" "\ 2359\ " 2360 "bne L%=_last_delay_T1H" "\ 2361\ " 2362 "strb %[bitmask], 2363 [%[reg], #4]" "\ 2364\ " 2365 "movs %[dly], #1" "\ 2366\ " 2367 "L%=_last_delay_T1L:" "\ 2368\ " 2369 "sub %[dly], 2370 #1" "\ 2371\ " 2372 "bne L%=_last_delay_T1L" "\ 2373\ " 2374 "nop" "\ 2375\ " 2376 "L%=_repeat:" "\ 2377\ " 2378 "add %[p], 2379 #1" "\ 2380\ " 2381 "sub %[num], #1" "\ 2382\ " 2383 "bne L%=_begin" "\ 2384\ " 2385 "L%=_done:" "\ 2386\ " 2387 : 2388 [p] "+r" (p), 2389 [pix] "=&r" (pix), 2390 [count] "=&r" (count), 2391 2392 [dly] "=&r" (dly), 2393 [num] "+r" (num) 2394 : [bitmask] "r" (bitmask), 2395 2396 [reg] "r" (reg) 2397 ); 2398#else 2399#error "Sorry, only 48 MHz is supported, 2400 please set Tools > CPU Speed to 48 MHz" 2401#endif // F_CPU == 48000000 2402 2403// 2404 Begin of support for NRF52832 based boards ------------------------- 2405 2406#elif 2407 defined(NRF52) 2408// [[[Begin of the Neopixel NRF52 EasyDMA implementation 2409// 2410 by the Hackerspace San Salvador]]] 2411// This 2412 technique uses the PWM peripheral on the NRF52. The PWM uses the 2413// EasyDMA feature 2414 included on the chip. This technique loads the duty 2415// cycle configuration for 2416 each cycle when the PWM is enabled. For this 2417// to work we need to store a 16 2418 bit configuration for each bit of the 2419// RGB(W) values in the pixel buffer. 2420// 2421 Comparator values for the PWM were hand picked and are guaranteed to 2422// be 100% 2423 organic to preserve freshness and high accuracy. Current 2424// parameters are: 2425// 2426 * PWM Clock: 16Mhz 2427// * Minimum step time: 62.5ns 2428// * Time for zero 2429 in high (T0H): 0.31ms 2430// * Time for one in high (T1H): 0.75ms 2431// * Cycle 2432 time: 1.25us 2433// * Frequency: 800Khz 2434// For 400Khz we just double the calculated 2435 times. 2436// ---------- BEGIN Constants for the EasyDMA implementation ----------- 2437// 2438 The PWM starts the duty cycle in LOW. To start with HIGH we 2439// need to set the 2440 15th bit on each register. 2441 2442// WS2812 (rev A) timing is 0.35 and 0.7us 2443//#define 2444 MAGIC_T0H 5UL | (0x8000) // 0.3125us 2445//#define MAGIC_T1H 12UL 2446 | (0x8000) // 0.75us 2447 2448// WS2812B (rev B) timing is 0.4 and 0.8 us 2449#define 2450 MAGIC_T0H 6UL | (0x8000) // 0.375us 2451#define MAGIC_T1H 13UL 2452 | (0x8000) // 0.8125us 2453 2454// WS2811 (400 khz) timing is 0.5 and 1.2 2455#define 2456 MAGIC_T0H_400KHz 8UL | (0x8000) // 0.5us 2457#define MAGIC_T1H_400KHz 19UL 2458 | (0x8000) // 1.1875us 2459 2460// For 400Khz, we double value of CTOPVAL 2461#define 2462 CTOPVAL 20UL // 1.25us 2463#define CTOPVAL_400KHz 40UL 2464 // 2.5us 2465 2466// ---------- END Constants for the EasyDMA implementation 2467 ------------- 2468// 2469// If there is no device available an alternative cycle-counter 2470// 2471 implementation is tried. 2472// The nRF52832 runs with a fixed clock of 64Mhz. The 2473 alternative 2474// implementation is the same as the one used for the Teensy 3.0/1/2 2475 but 2476// with the Nordic SDK HAL & registers syntax. 2477// The number of cycles 2478 was hand picked and is guaranteed to be 100% 2479// organic to preserve freshness 2480 and high accuracy. 2481// ---------- BEGIN Constants for cycle counter implementation 2482 --------- 2483#define CYCLES_800_T0H 18 // ~0.36 uS 2484#define CYCLES_800_T1H 41 2485 // ~0.76 uS 2486#define CYCLES_800 71 // ~1.25 uS 2487 2488#define CYCLES_400_T0H 2489 26 // ~0.50 uS 2490#define CYCLES_400_T1H 70 // ~1.26 uS 2491#define CYCLES_400 2492 156 // ~2.50 uS 2493// ---------- END of Constants for cycle counter implementation 2494 -------- 2495 2496 // To support both the SoftDevice + Neopixels we use the EasyDMA 2497 2498 // feature from the NRF25. However this technique implies to 2499 // generate 2500 a pattern and store it on the memory. The actual 2501 // memory used in bytes corresponds 2502 to the following formula: 2503 // totalMem = numBytes*8*2+(2*2) 2504 2505 // The two additional bytes at the end are needed to reset the 2506 // sequence. 2507 2508 // 2509 // If there is not enough memory, we will fall back to cycle counter 2510 2511 // using DWT 2512 uint32_t pattern_size = numBytes*8*sizeof(uint16_t)+2*sizeof(uint16_t); 2513 2514 uint16_t* pixels_pattern = NULL; 2515 2516 NRF_PWM_Type* pwm = NULL; 2517 2518 // 2519 Try to find a free PWM device, which is not enabled 2520 // and has no connected 2521 pins 2522 NRF_PWM_Type* PWM[3] = {NRF_PWM0, NRF_PWM1, NRF_PWM2}; 2523 for(int device 2524 = 0; device<3; device++) { 2525 if( (PWM[device]->ENABLE == 0) && 2526 2527 (PWM[device]->PSEL.OUT[0] & PWM_PSEL_OUT_CONNECT_Msk) && 2528 (PWM[device]->PSEL.OUT[1] 2529 & PWM_PSEL_OUT_CONNECT_Msk) && 2530 (PWM[device]->PSEL.OUT[2] & PWM_PSEL_OUT_CONNECT_Msk) 2531 && 2532 (PWM[device]->PSEL.OUT[3] & PWM_PSEL_OUT_CONNECT_Msk) 2533 ) { 2534 2535 pwm = PWM[device]; 2536 break; 2537 } 2538 } 2539 2540 // only malloc 2541 if there is PWM device available 2542 if ( pwm != NULL ) { 2543 #ifdef ARDUINO_FEATHER52 2544 // use thread-safe malloc 2545 pixels_pattern = (uint16_t *) rtos_malloc(pattern_size); 2546 2547 #else 2548 pixels_pattern = (uint16_t *) malloc(pattern_size); 2549 #endif 2550 2551 } 2552 2553 // Use the identified device to choose the implementation 2554 // If 2555 a PWM device is available use DMA 2556 if( (pixels_pattern != NULL) && (pwm != NULL) 2557 ) { 2558 uint16_t pos = 0; // bit position 2559 2560 for(uint16_t n=0; n<numBytes; 2561 n++) { 2562 uint8_t pix = pixels[n]; 2563 2564 for(uint8_t mask=0x80, i=0; 2565 mask>0; mask >>= 1, i++) { 2566 #ifdef NEO_KHZ400 2567 if( !is800KHz 2568 ) { 2569 pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H_400KHz : MAGIC_T0H_400KHz; 2570 2571 }else 2572 #endif 2573 { 2574 pixels_pattern[pos] = 2575 (pix & mask) ? MAGIC_T1H : MAGIC_T0H; 2576 } 2577 2578 pos++; 2579 } 2580 2581 } 2582 2583 // Zero padding to indicate the end of que sequence 2584 pixels_pattern[++pos] 2585 = 0 | (0x8000); // Seq end 2586 pixels_pattern[++pos] = 0 | (0x8000); // Seq end 2587 2588 2589 // Set the wave mode to count UP 2590 pwm->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos); 2591 2592 2593 // Set the PWM to use the 16MHz clock 2594 pwm->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 2595 << PWM_PRESCALER_PRESCALER_Pos); 2596 2597 // Setting of the maximum count 2598 2599 // but keeping it on 16Mhz allows for more granularity just 2600 // in case 2601 someone wants to do more fine-tuning of the timing. 2602#ifdef NEO_KHZ400 2603 if( 2604 !is800KHz ) { 2605 pwm->COUNTERTOP = (CTOPVAL_400KHz << PWM_COUNTERTOP_COUNTERTOP_Pos); 2606 2607 }else 2608#endif 2609 { 2610 pwm->COUNTERTOP = (CTOPVAL << PWM_COUNTERTOP_COUNTERTOP_Pos); 2611 2612 } 2613 2614 // Disable loops, we want the sequence to repeat only once 2615 2616 pwm->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos); 2617 2618 // On the 2619 "Common" setting the PWM uses the same pattern for the 2620 // for supported 2621 sequences. The pattern is stored on half-word 2622 // of 16bits 2623 pwm->DECODER 2624 = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | 2625 (PWM_DECODER_MODE_RefreshCount 2626 << PWM_DECODER_MODE_Pos); 2627 2628 // Pointer to the memory storing the patter 2629 2630 pwm->SEQ[0].PTR = (uint32_t)(pixels_pattern) << PWM_SEQ_PTR_PTR_Pos; 2631 2632 2633 // Calculation of the number of steps loaded from memory. 2634 pwm->SEQ[0].CNT 2635 = (pattern_size/sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos; 2636 2637 // The following 2638 settings are ignored with the current config. 2639 pwm->SEQ[0].REFRESH = 0; 2640 2641 pwm->SEQ[0].ENDDELAY = 0; 2642 2643 // The Neopixel implementation is a blocking 2644 algorithm. DMA 2645 // allows for non-blocking operation. To "simulate" a blocking 2646 2647 // operation we enable the interruption for the end of sequence 2648 // and 2649 block the execution thread until the event flag is set by 2650 // the peripheral. 2651// 2652 pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos); 2653 2654 // 2655 PSEL must be configured before enabling PWM 2656 pwm->PSEL.OUT[0] = g_ADigitalPinMap[pin]; 2657 2658 2659 // Enable the PWM 2660 pwm->ENABLE = 1; 2661 2662 // After all of this and 2663 many hours of reading the documentation 2664 // we are ready to start the sequence... 2665 2666 pwm->EVENTS_SEQEND[0] = 0; 2667 pwm->TASKS_SEQSTART[0] = 1; 2668 2669 // 2670 But we have to wait for the flag to be set. 2671 while(!pwm->EVENTS_SEQEND[0]) 2672 2673 { 2674 #ifdef ARDUINO_FEATHER52 2675 yield(); 2676 #endif 2677 } 2678 2679 2680 // Before leave we clear the flag for the event. 2681 pwm->EVENTS_SEQEND[0] 2682 = 0; 2683 2684 // We need to disable the device and disconnect 2685 // all the 2686 outputs before leave or the device will not 2687 // be selected on the next call. 2688 2689 // TODO: Check if disabling the device causes performance issues. 2690 pwm->ENABLE 2691 = 0; 2692 2693 pwm->PSEL.OUT[0] = 0xFFFFFFFFUL; 2694 2695 #ifdef ARDUINO_FEATHER52 2696 // use thread-safe free 2697 rtos_free(pixels_pattern); 2698 #else 2699 free(pixels_pattern); 2700 2701 #endif 2702 }// End of DMA implementation 2703 // --------------------------------------------------------------------- 2704 2705 else{ 2706 // Fall back to DWT 2707 #ifdef ARDUINO_FEATHER52 2708 // Bluefruit 2709 Feather 52 uses freeRTOS 2710 // Critical Section is used since it does not 2711 block SoftDevice execution 2712 taskENTER_CRITICAL(); 2713 #elif defined(NRF52_DISABLE_INT) 2714 2715 // If you are using the Bluetooth SoftDevice we advise you to not disable 2716 2717 // the interrupts. Disabling the interrupts even for short periods of time 2718 2719 // causes the SoftDevice to stop working. 2720 // Disable the interrupts 2721 only in cases where you need high performance for 2722 // the LEDs and if you 2723 are not using the EasyDMA feature. 2724 __disable_irq(); 2725 #endif 2726 2727 2728 uint32_t pinMask = 1UL << g_ADigitalPinMap[pin]; 2729 2730 uint32_t CYCLES_X00 2731 = CYCLES_800; 2732 uint32_t CYCLES_X00_T1H = CYCLES_800_T1H; 2733 uint32_t 2734 CYCLES_X00_T0H = CYCLES_800_T0H; 2735 2736#ifdef NEO_KHZ400 2737 if( !is800KHz ) 2738 2739 { 2740 CYCLES_X00 = CYCLES_400; 2741 CYCLES_X00_T1H = CYCLES_400_T1H; 2742 2743 CYCLES_X00_T0H = CYCLES_400_T0H; 2744 } 2745#endif 2746 2747 // Enable DWT 2748 in debug core 2749 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; 2750 DWT->CTRL 2751 |= DWT_CTRL_CYCCNTENA_Msk; 2752 2753 // Tries to re-send the frame if is interrupted 2754 by the SoftDevice. 2755 while(1) { 2756 uint8_t *p = pixels; 2757 2758 uint32_t 2759 cycStart = DWT->CYCCNT; 2760 uint32_t cyc = 0; 2761 2762 for(uint16_t n=0; 2763 n<numBytes; n++) { 2764 uint8_t pix = *p++; 2765 2766 for(uint8_t mask 2767 = 0x80; mask; mask >>= 1) { 2768 while(DWT->CYCCNT - cyc < CYCLES_X00); 2769 2770 cyc = DWT->CYCCNT; 2771 2772 NRF_GPIO->OUTSET |= pinMask; 2773 2774 2775 if(pix & mask) { 2776 while(DWT->CYCCNT - cyc < CYCLES_X00_T1H); 2777 2778 } else { 2779 while(DWT->CYCCNT - cyc < CYCLES_X00_T0H); 2780 2781 } 2782 2783 NRF_GPIO->OUTCLR |= pinMask; 2784 } 2785 } 2786 2787 while(DWT->CYCCNT - cyc < CYCLES_X00); 2788 2789 2790 // If total time longer 2791 than 25%, resend the whole data. 2792 // Since we are likely to be interrupted 2793 by SoftDevice 2794 if ( (DWT->CYCCNT - cycStart) < ( 8*numBytes*((CYCLES_X00*5)/4) 2795 ) ) { 2796 break; 2797 } 2798 2799 // re-send need 300us delay 2800 2801 delayMicroseconds(300); 2802 } 2803 2804 // Enable interrupts again 2805 2806 #ifdef ARDUINO_FEATHER52 2807 taskEXIT_CRITICAL(); 2808 #elif defined(NRF52_DISABLE_INT) 2809 2810 __enable_irq(); 2811 #endif 2812 } 2813// END of NRF52 implementation 2814 2815#elif 2816 defined (__SAMD21E17A__) || defined(__SAMD21G18A__) || defined(__SAMD21E18A__) 2817 || defined(__SAMD21J18A__) // Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo and 2818 others 2819 // Tried this with a timer/counter, couldn't quite get adequate 2820 2821 // resolution. So yay, you get a load of goofball NOPs... 2822 2823 uint8_t *ptr, 2824 *end, p, bitMask, portNum; 2825 uint32_t pinMask; 2826 2827 portNum = g_APinDescription[pin].ulPort; 2828 2829 pinMask = 1ul << g_APinDescription[pin].ulPin; 2830 ptr = pixels; 2831 end 2832 = ptr + numBytes; 2833 p = *ptr++; 2834 bitMask = 0x80; 2835 2836 volatile 2837 uint32_t *set = &(PORT->Group[portNum].OUTSET.reg), 2838 *clr 2839 = &(PORT->Group[portNum].OUTCLR.reg); 2840 2841#ifdef NEO_KHZ400 // 800 KHz check 2842 needed only if 400 KHz support enabled 2843 if(is800KHz) { 2844#endif 2845 for(;;) 2846 { 2847 *set = pinMask; 2848 asm("nop; nop; nop; nop; nop; nop; nop; nop;"); 2849 2850 if(p & bitMask) { 2851 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2852 2853 "nop; nop; nop; nop; nop; nop; nop; nop;" 2854 "nop; nop; 2855 nop; nop;"); 2856 *clr = pinMask; 2857 } else { 2858 *clr = pinMask; 2859 2860 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2861 "nop; nop; 2862 nop; nop; nop; nop; nop; nop;" 2863 "nop; nop; nop; nop;"); 2864 } 2865 2866 if(bitMask >>= 1) { 2867 asm("nop; nop; nop; nop; nop; nop; nop; nop; 2868 nop;"); 2869 } else { 2870 if(ptr >= end) break; 2871 p = 2872 *ptr++; 2873 bitMask = 0x80; 2874 } 2875 } 2876#ifdef NEO_KHZ400 2877 2878 } else { // 400 KHz bitstream 2879 for(;;) { 2880 *set = pinMask; 2881 asm("nop; 2882 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); 2883 if(p & bitMask) { 2884 2885 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2886 "nop; nop; 2887 nop; nop; nop; nop; nop; nop;" 2888 "nop; nop; nop; nop; nop; nop; nop; 2889 nop;" 2890 "nop; nop; nop;"); 2891 *clr = pinMask; 2892 } 2893 else { 2894 *clr = pinMask; 2895 asm("nop; nop; nop; nop; nop; nop; 2896 nop; nop;" 2897 "nop; nop; nop; nop; nop; nop; nop; nop;" 2898 "nop; 2899 nop; nop; nop; nop; nop; nop; nop;" 2900 "nop; nop; nop;"); 2901 } 2902 2903 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2904 "nop; nop; nop; 2905 nop; nop; nop; nop; nop;" 2906 "nop; nop; nop; nop; nop; nop; nop; nop;" 2907 2908 "nop; nop; nop; nop; nop; nop; nop; nop;"); 2909 if(bitMask >>= 2910 1) { 2911 asm("nop; nop; nop; nop; nop; nop; nop;"); 2912 } else { 2913 2914 if(ptr >= end) break; 2915 p = *ptr++; 2916 bitMask = 2917 0x80; 2918 } 2919 } 2920 } 2921#endif 2922 2923#elif defined (__SAMD51__) // 2924 M4 @ 120mhz 2925 // Tried this with a timer/counter, couldn't quite get adequate 2926 2927 // resolution. So yay, you get a load of goofball NOPs... 2928 2929 uint8_t *ptr, 2930 *end, p, bitMask, portNum; 2931 uint32_t pinMask; 2932 2933 portNum = g_APinDescription[pin].ulPort; 2934 2935 pinMask = 1ul << g_APinDescription[pin].ulPin; 2936 ptr = pixels; 2937 end 2938 = ptr + numBytes; 2939 p = *ptr++; 2940 bitMask = 0x80; 2941 2942 volatile 2943 uint32_t *set = &(PORT->Group[portNum].OUTSET.reg), 2944 *clr 2945 = &(PORT->Group[portNum].OUTCLR.reg); 2946 2947#ifdef NEO_KHZ400 // 800 KHz check 2948 needed only if 400 KHz support enabled 2949 if(is800KHz) { 2950#endif 2951 for(;;) 2952 { 2953 if(p & bitMask) { // ONE 2954 // High 800ns 2955 *set = pinMask; 2956 2957 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 2958 "nop; nop; 2959 nop; nop; nop; nop; nop; nop;" 2960 "nop; nop; nop; nop; nop; nop; nop; 2961 nop;" 2962 "nop; nop; nop; nop; nop; nop; nop; nop;" 2963 "nop; 2964 nop; nop; nop; nop; nop; nop; nop;" 2965 "nop; nop; nop; nop; nop; nop; 2966 nop; nop;" 2967 "nop; nop; nop; nop; nop; nop; nop; nop;" 2968 "nop; 2969 nop; nop; nop; nop; nop; nop; nop;" 2970 "nop; nop; nop; nop; nop; nop; 2971 nop; nop;" 2972 "nop; nop; nop; nop; nop; nop; nop; nop;"); 2973 // 2974 Low 450ns 2975 *clr = pinMask; 2976 asm("nop; nop; nop; nop; nop; nop; 2977 nop; nop;" 2978 "nop; nop; nop; nop; nop; nop; nop; nop;" 2979 "nop; 2980 nop; nop; nop; nop; nop; nop; nop;" 2981 "nop; nop; nop; nop; nop; nop; 2982 nop; nop;" 2983 "nop;"); 2984 } else { // ZERO 2985 // High 2986 400ns 2987 *set = pinMask; 2988 asm("nop; nop; nop; nop; nop; nop; 2989 nop; nop;" 2990 "nop; nop; nop; nop; nop; nop; nop; nop;" 2991 "nop; 2992 nop; nop; nop; nop; nop; nop; nop;" 2993 "nop; nop; nop; nop; nop; nop; 2994 nop; nop;" 2995 "nop;"); 2996 // Low 850ns 2997 *clr = 2998 pinMask; 2999 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 3000 "nop; 3001 nop; nop; nop; nop; nop; nop; nop;" 3002 "nop; nop; nop; nop; nop; nop; 3003 nop; nop;" 3004 "nop; nop; nop; nop; nop; nop; nop; nop;" 3005 "nop; 3006 nop; nop; nop; nop; nop; nop; nop;" 3007 "nop; nop; nop; nop; nop; nop; 3008 nop; nop;" 3009 "nop; nop; nop; nop; nop; nop; nop; nop;" 3010 "nop; 3011 nop; nop; nop; nop; nop; nop; nop;" 3012 "nop; nop; nop; nop; nop; nop; 3013 nop; nop;" 3014 "nop; nop; nop; nop; nop; nop; nop; nop;"); 3015 } 3016 3017 if(bitMask >>= 1) { 3018 // Move on to the next pixel 3019 asm("nop;"); 3020 3021 } else { 3022 if(ptr >= end) break; 3023 p = *ptr++; 3024 3025 bitMask = 0x80; 3026 } 3027 } 3028#ifdef NEO_KHZ400 3029 } else { // 3030 400 KHz bitstream 3031 // ToDo! 3032 } 3033#endif 3034 3035#elif defined (ARDUINO_STM32_FEATHER) 3036 // FEATHER WICED (120MHz) 3037 3038 // Tried this with a timer/counter, couldn't 3039 quite get adequate 3040 // resolution. So yay, you get a load of goofball NOPs... 3041 3042 3043 uint8_t *ptr, *end, p, bitMask; 3044 uint32_t pinMask; 3045 3046 pinMask = BIT(PIN_MAP[pin].gpio_bit); 3047 3048 ptr = pixels; 3049 end = ptr + numBytes; 3050 p = *ptr++; 3051 3052 bitMask = 0x80; 3053 3054 volatile uint16_t *set = &(PIN_MAP[pin].gpio_device->regs->BSRRL); 3055 3056 volatile uint16_t *clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH); 3057 3058#ifdef 3059 NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled 3060 if(is800KHz) 3061 { 3062#endif 3063 for(;;) { 3064 if(p & bitMask) { // ONE 3065 // High 3066 800ns 3067 *set = pinMask; 3068 asm("nop; nop; nop; nop; nop; nop; 3069 nop; nop;" 3070 "nop; nop; nop; nop; nop; nop; nop; nop;" 3071 "nop; 3072 nop; nop; nop; nop; nop; nop; nop;" 3073 "nop; nop; nop; nop; nop; nop; 3074 nop; nop;" 3075 "nop; nop; nop; nop; nop; nop; nop; nop;" 3076 "nop; 3077 nop; nop; nop; nop; nop; nop; nop;" 3078 "nop; nop; nop; nop; nop; nop; 3079 nop; nop;" 3080 "nop; nop; nop; nop; nop; nop; nop; nop;" 3081 "nop; 3082 nop; nop; nop; nop; nop; nop; nop;" 3083 "nop; nop; nop; nop; nop; nop; 3084 nop; nop;" 3085 "nop; nop; nop; nop; nop; nop; nop; nop;" 3086 "nop; 3087 nop; nop; nop; nop; nop;"); 3088 // Low 450ns 3089 *clr = pinMask; 3090 3091 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 3092 "nop; nop; 3093 nop; nop; nop; nop; nop; nop;" 3094 "nop; nop; nop; nop; nop; nop; nop; 3095 nop;" 3096 "nop; nop; nop; nop; nop; nop; nop; nop;" 3097 "nop; 3098 nop; nop; nop; nop; nop;"); 3099 } else { // ZERO 3100 // High 400ns 3101 3102 *set = pinMask; 3103 asm("nop; nop; nop; nop; nop; nop; nop; nop;" 3104 3105 "nop; nop; nop; nop; nop; nop; nop; nop;" 3106 "nop; nop; 3107 nop; nop; nop; nop; nop; nop;" 3108 "nop; nop; nop; nop; nop; nop; nop; 3109 nop;" 3110 "nop; nop; nop; nop; nop; nop; nop; nop;" 3111 "nop;"); 3112 3113 // Low 850ns 3114 *clr = pinMask; 3115 asm("nop; nop; nop; 3116 nop; nop; nop; nop; nop;" 3117 "nop; nop; nop; nop; nop; nop; nop; nop;" 3118 3119 "nop; nop; nop; nop; nop; nop; nop; nop;" 3120 "nop; nop; 3121 nop; nop; nop; nop; nop; nop;" 3122 "nop; nop; nop; nop; nop; nop; nop; 3123 nop;" 3124 "nop; nop; nop; nop; nop; nop; nop; nop;" 3125 "nop; 3126 nop; nop; nop; nop; nop; nop; nop;" 3127 "nop; nop; nop; nop; nop; nop; 3128 nop; nop;" 3129 "nop; nop; nop; nop; nop; nop; nop; nop;" 3130 "nop; 3131 nop; nop; nop; nop; nop; nop; nop;" 3132 "nop; nop; nop; nop; nop; nop; 3133 nop; nop;" 3134 "nop; nop; nop; nop;"); 3135 } 3136 if(bitMask 3137 >>= 1) { 3138 // Move on to the next pixel 3139 asm("nop;"); 3140 } 3141 else { 3142 if(ptr >= end) break; 3143 p = *ptr++; 3144 bitMask 3145 = 0x80; 3146 } 3147 } 3148#ifdef NEO_KHZ400 3149 } else { // 400 KHz bitstream 3150 3151 // ToDo! 3152 } 3153#endif 3154 3155#else // Other ARM architecture -- Presumed 3156 Arduino Due 3157 3158 #define SCALE VARIANT_MCK / 2UL / 1000000UL 3159 #define 3160 INST (2UL * F_CPU / VARIANT_MCK) 3161 #define TIME_800_0 ((int)(0.40 * SCALE 3162 + 0.5) - (5 * INST)) 3163 #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST)) 3164 3165 #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST)) 3166 #define TIME_400_0 3167 ((int)(0.50 * SCALE + 0.5) - (5 * INST)) 3168 #define TIME_400_1 ((int)(1.20 * SCALE 3169 + 0.5) - (5 * INST)) 3170 #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST)) 3171 3172 3173 int pinMask, time0, time1, period, t; 3174 Pio *port; 3175 3176 volatile WoReg *portSet, *portClear, *timeValue, *timeReset; 3177 uint8_t *p, 3178 *end, pix, mask; 3179 3180 pmc_set_writeprotect(false); 3181 pmc_enable_periph_clk((uint32_t)TC3_IRQn); 3182 3183 TC_Configure(TC1, 0, 3184 TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1); 3185 3186 TC_Start(TC1, 0); 3187 3188 pinMask = g_APinDescription[pin].ulPin; // Don't 3189 'optimize' these into 3190 port = g_APinDescription[pin].pPort; // declarations 3191 above. Want to 3192 portSet = &(port->PIO_SODR); // burn a few cycles 3193 after 3194 portClear = &(port->PIO_CODR); // starting timer to minimize 3195 3196 timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'. 3197 timeReset 3198 = &(TC1->TC_CHANNEL[0].TC_CCR); 3199 p = pixels; 3200 end = p + 3201 numBytes; 3202 pix = *p++; 3203 mask = 0x80; 3204 3205#ifdef NEO_KHZ400 3206 // 800 KHz check needed only if 400 KHz support enabled 3207 if(is800KHz) { 3208#endif 3209 3210 time0 = TIME_800_0; 3211 time1 = TIME_800_1; 3212 period = PERIOD_800; 3213#ifdef 3214 NEO_KHZ400 3215 } else { // 400 KHz bitstream 3216 time0 = TIME_400_0; 3217 time1 3218 = TIME_400_1; 3219 period = PERIOD_400; 3220 } 3221#endif 3222 3223 for(t = time0;; 3224 t = time0) { 3225 if(pix & mask) t = time1; 3226 while(*timeValue < period); 3227 3228 *portSet = pinMask; 3229 *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG; 3230 while(*timeValue 3231 < t); 3232 *portClear = pinMask; 3233 if(!(mask >>= 1)) { // This 'inside-out' 3234 loop logic utilizes 3235 if(p >= end) break; // idle time to minimize inter-byte 3236 delays. 3237 pix = *p++; 3238 mask = 0x80; 3239 } 3240 } 3241 while(*timeValue 3242 < period); // Wait for last bit 3243 TC_Stop(TC1, 0); 3244 3245#endif // end Due 3246 3247// 3248 END ARM ---------------------------------------------------------------- 3249 3250 3251#elif 3252 defined(ESP8266) || defined(ESP32) 3253 3254// ESP8266 ---------------------------------------------------------------- 3255 3256 3257 // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution 3258 espShow(pin, 3259 pixels, numBytes, is800KHz); 3260 3261#elif defined(__ARDUINO_ARC__) 3262 3263// Arduino 3264 101 ----------------------------------------------------------- 3265 3266#define 3267 NOPx7 { __builtin_arc_nop(); \\ 3268 __builtin_arc_nop(); __builtin_arc_nop(); \\ 3269 3270 __builtin_arc_nop(); __builtin_arc_nop(); \\ 3271 __builtin_arc_nop(); __builtin_arc_nop(); 3272 } 3273 3274 PinDescription *pindesc = &g_APinDescription[pin]; 3275 register uint32_t 3276 loop = 8 * numBytes; // one loop to handle all bytes and all bits 3277 register 3278 uint8_t *p = pixels; 3279 register uint32_t currByte = (uint32_t) (*p); 3280 register 3281 uint32_t currBit = 0x80 & currByte; 3282 register uint32_t bitCounter = 0; 3283 register 3284 uint32_t first = 1; 3285 3286 // The loop is unusual. Very first iteration puts all 3287 the way LOW to the wire - 3288 // constant LOW does not affect NEOPIXEL, so there 3289 is no visible effect displayed. 3290 // During that very first iteration CPU caches 3291 instructions in the loop. 3292 // Because of the caching process, "CPU slows down". 3293 NEOPIXEL pulse is very time sensitive 3294 // that's why we let the CPU cache first 3295 and we start regular pulse from 2nd iteration 3296 if (pindesc->ulGPIOType == SS_GPIO) 3297 { 3298 register uint32_t reg = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR; 3299 uint32_t 3300 reg_val = __builtin_arc_lr((volatile uint32_t)reg); 3301 register uint32_t reg_bit_high 3302 = reg_val | (1 << pindesc->ulGPIOId); 3303 register uint32_t reg_bit_low = reg_val 3304 & ~(1 << pindesc->ulGPIOId); 3305 3306 loop += 1; // include first, special iteration 3307 3308 while(loop--) { 3309 if(!first) { 3310 currByte <<= 1; 3311 bitCounter++; 3312 3313 } 3314 3315 // 1 is >550ns high and >450ns low; 0 is 200..500ns high and 3316 >450ns low 3317 __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile 3318 uint32_t)reg); 3319 if(currBit) { // ~400ns HIGH (740ns overall) 3320 NOPx7 3321 3322 NOPx7 3323 } 3324 // ~340ns HIGH 3325 NOPx7 3326 __builtin_arc_nop(); 3327 3328 3329 // 820ns LOW; per spec, max allowed low here is 5000ns */ 3330 __builtin_arc_sr(reg_bit_low, 3331 (volatile uint32_t)reg); 3332 NOPx7 3333 NOPx7 3334 3335 if(bitCounter 3336 >= 8) { 3337 bitCounter = 0; 3338 currByte = (uint32_t) (*++p); 3339 3340 } 3341 3342 currBit = 0x80 & currByte; 3343 first = 0; 3344 } 3345 3346 } else if(pindesc->ulGPIOType == SOC_GPIO) { 3347 register uint32_t reg = pindesc->ulGPIOBase 3348 + SOC_GPIO_SWPORTA_DR; 3349 uint32_t reg_val = MMIO_REG_VAL(reg); 3350 register 3351 uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId); 3352 register uint32_t 3353 reg_bit_low = reg_val & ~(1 << pindesc->ulGPIOId); 3354 3355 loop += 1; // include 3356 first, special iteration 3357 while(loop--) { 3358 if(!first) { 3359 currByte 3360 <<= 1; 3361 bitCounter++; 3362 } 3363 MMIO_REG_VAL(reg) = first ? 3364 reg_bit_low : reg_bit_high; 3365 if(currBit) { // ~430ns HIGH (740ns overall) 3366 3367 NOPx7 3368 NOPx7 3369 __builtin_arc_nop(); 3370 } 3371 // 3372 ~310ns HIGH 3373 NOPx7 3374 3375 // 850ns LOW; per spec, max allowed low 3376 here is 5000ns */ 3377 MMIO_REG_VAL(reg) = reg_bit_low; 3378 NOPx7 3379 NOPx7 3380 3381 3382 if(bitCounter >= 8) { 3383 bitCounter = 0; 3384 currByte = (uint32_t) 3385 (*++p); 3386 } 3387 3388 currBit = 0x80 & currByte; 3389 first = 0; 3390 3391 } 3392 } 3393 3394#else 3395#error Architecture not supported 3396#endif 3397 3398 3399// 3400 END ARCHITECTURE SELECT ------------------------------------------------ 3401 3402#ifndef 3403 NRF52 3404 interrupts(); 3405#endif 3406 3407 endTime = micros(); // Save EOD time 3408 for latch on next call 3409} 3410 3411// Set the output pin number 3412void Adafruit_NeoPixel::setPin(uint8_t 3413 p) { 3414 if(begun && (pin >= 0)) pinMode(pin, INPUT); 3415 pin = p; 3416 if(begun) 3417 { 3418 pinMode(p, OUTPUT); 3419 digitalWrite(p, LOW); 3420 } 3421#ifdef 3422 __AVR__ 3423 port = portOutputRegister(digitalPinToPort(p)); 3424 pinMask 3425 = digitalPinToBitMask(p); 3426#endif 3427} 3428 3429// Set pixel color from separate 3430 R,G,B components: 3431void Adafruit_NeoPixel::setPixelColor( 3432 uint16_t n, uint8_t 3433 r, uint8_t g, uint8_t b) { 3434 3435 if(n < numLEDs) { 3436 if(brightness) { // 3437 See notes in setBrightness() 3438 r = (r * brightness) >> 8; 3439 g = (g 3440 * brightness) >> 8; 3441 b = (b * brightness) >> 8; 3442 } 3443 uint8_t 3444 *p; 3445 if(wOffset == rOffset) { // Is an RGB-type strip 3446 p = &pixels[n 3447 * 3]; // 3 bytes per pixel 3448 } else { // Is a WRGB-type 3449 strip 3450 p = &pixels[n * 4]; // 4 bytes per pixel 3451 p[wOffset] = 3452 0; // But only R,G,B passed -- set W to 0 3453 } 3454 p[rOffset] = r; 3455 // R,G,B always stored 3456 p[gOffset] = g; 3457 p[bOffset] = b; 3458 3459 } 3460} 3461 3462void Adafruit_NeoPixel::setPixelColor( 3463 uint16_t n, uint8_t r, 3464 uint8_t g, uint8_t b, uint8_t w) { 3465 3466 if(n < numLEDs) { 3467 if(brightness) 3468 { // See notes in setBrightness() 3469 r = (r * brightness) >> 8; 3470 g 3471 = (g * brightness) >> 8; 3472 b = (b * brightness) >> 8; 3473 w = (w * brightness) 3474 >> 8; 3475 } 3476 uint8_t *p; 3477 if(wOffset == rOffset) { // Is an RGB-type 3478 strip 3479 p = &pixels[n * 3]; // 3 bytes per pixel (ignore W) 3480 } else 3481 { // Is a WRGB-type strip 3482 p = &pixels[n * 4]; // 4 bytes 3483 per pixel 3484 p[wOffset] = w; // Store W 3485 } 3486 p[rOffset] 3487 = r; // Store R,G,B 3488 p[gOffset] = g; 3489 p[bOffset] = b; 3490 } 3491} 3492 3493// 3494 Set pixel color from 'packed' 32-bit RGB color: 3495void Adafruit_NeoPixel::setPixelColor(uint16_t 3496 n, uint32_t c) { 3497 if(n < numLEDs) { 3498 uint8_t *p, 3499 r = (uint8_t)(c 3500 >> 16), 3501 g = (uint8_t)(c >> 8), 3502 b = (uint8_t)c; 3503 if(brightness) 3504 { // See notes in setBrightness() 3505 r = (r * brightness) >> 8; 3506 g 3507 = (g * brightness) >> 8; 3508 b = (b * brightness) >> 8; 3509 } 3510 if(wOffset 3511 == rOffset) { 3512 p = &pixels[n * 3]; 3513 } else { 3514 p = &pixels[n 3515 * 4]; 3516 uint8_t w = (uint8_t)(c >> 24); 3517 p[wOffset] = brightness 3518 ? ((w * brightness) >> 8) : w; 3519 } 3520 p[rOffset] = r; 3521 p[gOffset] 3522 = g; 3523 p[bOffset] = b; 3524 } 3525} 3526 3527// Convert separate R,G,B into packed 3528 32-bit RGB color. 3529// Packed format is always RGB, regardless of LED strand color 3530 order. 3531uint32_t Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) { 3532 3533 return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 3534} 3535 3536// Convert separate 3537 R,G,B,W into packed 32-bit WRGB color. 3538// Packed format is always WRGB, regardless 3539 of LED strand color order. 3540uint32_t Adafruit_NeoPixel::Color(uint8_t r, uint8_t 3541 g, uint8_t b, uint8_t w) { 3542 return ((uint32_t)w << 24) | ((uint32_t)r << 16) 3543 | ((uint32_t)g << 8) | b; 3544} 3545 3546// Query color from previously-set pixel 3547 (returns packed 32-bit RGB value) 3548uint32_t Adafruit_NeoPixel::getPixelColor(uint16_t 3549 n) const { 3550 if(n >= numLEDs) return 0; // Out of bounds, return no color. 3551 3552 3553 uint8_t *p; 3554 3555 if(wOffset == rOffset) { // Is RGB-type device 3556 p = 3557 &pixels[n * 3]; 3558 if(brightness) { 3559 // Stored color was decimated by 3560 setBrightness(). Returned value 3561 // attempts to scale back to an approximation 3562 of the original 24-bit 3563 // value used when setting the pixel color, but 3564 there will always be 3565 // some error -- those bits are simply gone. Issue 3566 is most 3567 // pronounced at low brightness levels. 3568 return (((uint32_t)(p[rOffset] 3569 << 8) / brightness) << 16) | 3570 (((uint32_t)(p[gOffset] << 8) / brightness) 3571 << 8) | 3572 ( (uint32_t)(p[bOffset] << 8) / brightness ); 3573 3574 } else { 3575 // No brightness adjustment has been made -- return 'raw' 3576 color 3577 return ((uint32_t)p[rOffset] << 16) | 3578 ((uint32_t)p[gOffset] 3579 << 8) | 3580 (uint32_t)p[bOffset]; 3581 } 3582 } else { // 3583 Is RGBW-type device 3584 p = &pixels[n * 4]; 3585 if(brightness) { // Return 3586 scaled color 3587 return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) 3588 | 3589 (((uint32_t)(p[rOffset] << 8) / brightness) << 16) | 3590 (((uint32_t)(p[gOffset] 3591 << 8) / brightness) << 8) | 3592 ( (uint32_t)(p[bOffset] << 8) / brightness 3593 ); 3594 } else { // Return raw color 3595 return ((uint32_t)p[wOffset] 3596 << 24) | 3597 ((uint32_t)p[rOffset] << 16) | 3598 ((uint32_t)p[gOffset] 3599 << 8) | 3600 (uint32_t)p[bOffset]; 3601 } 3602 } 3603} 3604 3605// Returns 3606 pointer to pixels[] array. Pixel data is stored in device- 3607// native format 3608 and is not translated here. Application will need to be 3609// aware of specific 3610 pixel data format and handle colors appropriately. 3611uint8_t *Adafruit_NeoPixel::getPixels(void) 3612 const { 3613 return pixels; 3614} 3615 3616uint16_t Adafruit_NeoPixel::numPixels(void) 3617 const { 3618 return numLEDs; 3619} 3620 3621// Adjust output brightness; 0=darkest 3622 (off), 255=brightest. This does 3623// NOT immediately affect what's currently displayed 3624 on the LEDs. The 3625// next call to show() will refresh the LEDs at this level. 3626 However, 3627// this process is potentially "lossy," especially when increasing 3628// 3629 brightness. The tight timing in the WS2811/WS2812 code means there 3630// aren't 3631 enough free cycles to perform this scaling on the fly as data 3632// is issued. So 3633 we make a pass through the existing color data in RAM 3634// and scale it (subsequent 3635 graphics commands also work at this 3636// brightness level). If there's a significant 3637 step up in brightness, 3638// the limited number of steps (quantization) in the old 3639 data will be 3640// quite visible in the re-scaled version. For a non-destructive 3641// 3642 change, you'll need to re-render the full strip data. C'est la vie. 3643void Adafruit_NeoPixel::setBrightness(uint8_t 3644 b) { 3645 // Stored brightness value is different than what's passed. 3646 // This 3647 simplifies the actual scaling math later, allowing a fast 3648 // 8x8-bit multiply 3649 and taking the MSB. 'brightness' is a uint8_t, 3650 // adding 1 here may (intentionally) 3651 roll over...so 0 = max brightness 3652 // (color values are interpreted literally; 3653 no scaling), 1 = min 3654 // brightness (off), 255 = just below max brightness. 3655 3656 uint8_t newBrightness = b + 1; 3657 if(newBrightness != brightness) { // Compare 3658 against prior value 3659 // Brightness has changed -- re-scale existing data in 3660 RAM 3661 uint8_t c, 3662 *ptr = pixels, 3663 oldBrightness 3664 = brightness - 1; // De-wrap old brightness value 3665 uint16_t scale; 3666 if(oldBrightness 3667 == 0) scale = 0; // Avoid /0 3668 else if(b == 255) scale = 65535 / oldBrightness; 3669 3670 else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; 3671 for(uint16_t 3672 i=0; i<numBytes; i++) { 3673 c = *ptr; 3674 *ptr++ = (c * scale) >> 3675 8; 3676 } 3677 brightness = newBrightness; 3678 } 3679} 3680 3681//Return the brightness 3682 value 3683uint8_t Adafruit_NeoPixel::getBrightness(void) const { 3684 return brightness 3685 - 1; 3686} 3687 3688void Adafruit_NeoPixel::clear() { 3689 memset(pixels, 0, numBytes); 3690} 3691
RX8025.h
c_cpp
1#ifndef __RX8025_H__ 2#define __RX8025_H__ 3 4#define Set_Bit(P,N) 5 P |= (1<<N) 6#define Clear_Bit(P,N) P &=~(1<<N) 7 8//PC1 SDA /*I2C 9 */ 10 11#define SCL_OUT() Set_Bit(DDRC,5) 12#define SCL_IN() Clear_Bit(DDRC,5) 13#define 14 SCL_H() Set_Bit(PORTC,5) 15#define SCL_L() Clear_Bit(PORTC,5) 16 17#define 18 SDA_OUT() Set_Bit(DDRC,4) 19#define SDA_IN() Clear_Bit(DDRC,4) 20#define 21 SDA_H() Set_Bit(PORTC,4) 22#define SDA_L() Clear_Bit(PORTC,4) 23 24#define 25 SDA_INPUT() !(!(PINC & 0x10)) 26 27#define RX8025_ADD 0x64 28 // RX8025I2C 29#define RS8025_TIME_REG_START_ADD 0X00 //RX8050 30#define 31 RS8025_CONTROL_REG_ADD 0XE0 //RX8050 32 33void Start_I2c(); 34void 35 Stop_I2c(); 36void SendByte(unsigned char c); 37unsigned char RcvByte(); 38void 39 Ack_I2c(unsigned char a); 40unsigned char ISendStr(unsigned char sla,unsigned char 41 suba,unsigned char *s,unsigned char no); 42unsigned char IRcvStr(unsigned char 43 sla,unsigned char suba,unsigned char *s,unsigned char no); 44void RX8025_INIT (void); 45void 46 RX8025_READ (unsigned char *GetTime); 47void RX8025_WRITE (unsigned char *SetTime); 48 49#endif 50
Downloadable files
SchDoc
SchDoc
SchDoc
SchDoc
Comments
Only logged in users can leave comments