diff --git a/src/extras/Pixel.cpp b/src/extras/Pixel.cpp index ad990c5..6b32b5d 100644 --- a/src/extras/Pixel.cpp +++ b/src/extras/Pixel.cpp @@ -5,13 +5,13 @@ Pixel::Pixel(int pin, uint32_t nPixels){ - rf=new RFControl(pin,false); // set clock to 1/80 usec + rf=new RFControl(pin,false,false); // set clock to 1/80 usec, no default driver setTiming(0.32, 0.88, 0.64, 0.56, 80.0); // set default timing parameters (suitable for most SK68 and WS28 RGB pixels) - - if(nPixels==0) // must reserve at least enough memory for one pixel per transmission batch - nPixels=1; - nTrain=nPixels; + rmt_isr_register(isrHandler,(void *)this,0,NULL); // end-transmission interrupt automatically enabled by rmt_tx_start + rmt_set_tx_thr_intr_en(rf->getChannel(),true,8); // need to also enable threshold interrupt + channelNum=rf->getChannel(); + } /////////////////// @@ -41,28 +41,45 @@ void Pixel::setRGB(uint8_t r, uint8_t g, uint8_t b, int nPixels){ /////////////////// -void Pixel::setColors(color_t *color, int nPixels){ +void Pixel::setColors(const uint32_t *data, uint32_t nPixels){ - if(!*rf) - return; - - uint32_t *pulses = (uint32_t *) malloc(nTrain*24*sizeof(uint32_t)); - - if(!pulses){ - Serial.printf("*** ERROR: Not enough memory to reserve for %d Pixels per batch transmission\n",nTrain); + if(!*rf || nPixels==0) return; - } - int i,j; - - for(i=0;istart(pulses,j*24); - } + status.nPixels=nPixels; + status.data=data; + status.iMem=0; + status.iBit=24; + status.started=true; + status.txEndMask=TxEndMask(channelNum); - free(pulses); - delayMicroseconds(resetTime); + loadData(); // load first 2 bytes + loadData(); + + rmt_tx_start(rf->getChannel(),true); + + while(status.started); + + + return; + +// uint32_t *pulses = (uint32_t *) malloc(nTrain*24*sizeof(uint32_t)); +// +// if(!pulses){ +// Serial.printf("*** ERROR: Not enough memory to reserve for %d Pixels per batch transmission\n",nTrain); +// return; +// } +// +// int i,j; +// +// for(i=0;istart(pulses,j*24); +// } +// +// free(pulses); +// delayMicroseconds(resetTime); } /////////////////// @@ -101,3 +118,41 @@ color_t Pixel::getColorHSV(float h, float s, float v){ } /////////////////// + +void Pixel::loadData(){ + + if(status.nPixels==0){ + RMTMEM.chan[channelNum].data32[status.iMem].val=0; + return; + } + + for(int i=0;i<8;i++) + RMTMEM.chan[channelNum].data32[status.iMem++].val=pattern[(*status.data>>(--status.iBit))&1]; + + if(status.iBit==0){ + status.iBit=24; + status.data++; + status.nPixels--; + } + status.iMem%=memSize; +} + +/////////////////// + +void Pixel::isrHandler(void *arg){ + + Pixel *pix=(Pixel *)arg; + + if(RMT.int_st.val & status.txEndMask){ + RMT.int_clr.val=~0; + status.started=false; + return; + } + + RMT.int_clr.val=~0; + pix->loadData(); +} + +/////////////////// + +volatile pixel_status_t Pixel::status; diff --git a/src/extras/Pixel.h b/src/extras/Pixel.h index 01053f3..9b07509 100644 --- a/src/extras/Pixel.h +++ b/src/extras/Pixel.h @@ -10,13 +10,41 @@ typedef uint32_t color_t; +struct pixel_status_t { + int nPixels; + const uint32_t *data; + int iBit; + int iMem; + boolean started; + uint32_t txEndMask; // mask for end-of-transmission interrupt +}; + class Pixel { private: uint32_t pattern[2]; // storage for zero-bit and one-bit pulses uint32_t resetTime; // minimum time (in usec) between pulse trains + int channelNum; // channel number + uint32_t nTrain; // number of Pixels to transmit per pulse train batch + + #if defined(CONFIG_IDF_TARGET_ESP32) + const int memSize=64; + #define TxEndMask(chNum) (1<<(chNum*3)) + #elif defined(CONFIG_IDF_TARGET_ESP32S2) + const int memSize=48; + #define TxEndMask(chNum) (1<<(chNum*3)) + #elif defined(CONFIG_IDF_TARGET_ESP32C3) + const int memSize=48; + #define TxEndMask(chNum) (1<getPin());} // returns pixel pin if valid, else returns -1 static color_t getColorRGB(uint8_t r, uint8_t g, uint8_t b); // return pixel Color from RGB values static color_t getColorHSV(float h, float s, float v); // return pixel Color from HSV values + + void loadData(); operator bool(){ // override boolean operator to return true/false if creation succeeded/failed return(*rf); diff --git a/src/extras/RFControl.cpp b/src/extras/RFControl.cpp index 7d1a78f..182cefb 100644 --- a/src/extras/RFControl.cpp +++ b/src/extras/RFControl.cpp @@ -128,7 +128,6 @@ void RFControl::enableCarrier(uint32_t freq, float duty){ return; } -// Serial.printf("%d %g %d %d\n",freq,period,highTime,lowTime); rmt_set_tx_carrier(config->channel,true,highTime,lowTime,RMT_CARRIER_LEVEL_HIGH); } else { rmt_set_tx_carrier(config->channel,false,0,0,RMT_CARRIER_LEVEL_HIGH); diff --git a/src/extras/extras.ino b/src/extras/extras.ino index 226fad2..a944271 100644 --- a/src/extras/extras.ino +++ b/src/extras/extras.ino @@ -95,6 +95,23 @@ void setup() { Serial.println("\n\nHomeSpan Pixel Example\n"); + Pixel px(1); + + uint32_t colors[20]; + + colors[0]=px.getColorRGB(40,40,0); + colors[1]=px.getColorRGB(40,40,0); + colors[2]=px.getColorRGB(40,0,0); + colors[3]=px.getColorRGB(0,0,40); + colors[4]=px.getColorRGB(40,0,0); + colors[5]=px.getColorRGB(40,0,0); + colors[6]=px.getColorRGB(40,0,0); + colors[7]=px.getColorRGB(0,0,40); + + px.setColors(colors,8); + Serial.println("\n\nDone\n\n"); + while(1); + RFControl rf(PIN,true,false); rmt_set_clk_div(rf.getChannel(),100); // set clock divider