Updated RFControl for compatibility with ESP32-S2 and ESP32-C3

Complete re-write of code.
This commit is contained in:
Gregg 2021-10-03 12:08:33 -05:00
parent 82ad33c98f
commit dc5844b520
3 changed files with 124 additions and 93 deletions

View File

@ -7,49 +7,42 @@
///////////////////
RFControl::RFControl(int pin){
if(!configured){ // configure RMT peripheral
RFControl::RFControl(uint8_t pin){
DPORT_REG_SET_BIT(DPORT_PERIP_CLK_EN_REG,1<<9); // enable RMT clock by setting bit 9
DPORT_REG_CLR_BIT(DPORT_PERIP_RST_EN_REG,1<<9); // set RMT to normal ("un-reset") mode by clearing bit 9
REG_SET_BIT(RMT_APB_CONF_REG,3); // enables access to RMT memory and enables wraparound mode (though the latter does not seem to be needed to set continuous TX)
REG_WRITE(RMT_INT_ENA_REG,1<<RMT_CH0_TX_END_INT_ENA_S); // enable end-transmission interrupt so that interrupt vector is called
REG_WRITE(RMT_CH0CONF0_REG,0x08000000); // disable carrier wave; set channel 0 to use all 8 blocks of RMT memory
// esp_intr_alloc(ETS_RMT_INTR_SOURCE,0,eot_int,NULL,NULL); // set RMT general interrupt vector
// config=new rmt_config_t;
configured=true;
}
this->pin=pin;
pinMode(pin,OUTPUT);
REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG+4*pin,87); // set GPIO OUTPUT of pin in GPIO_MATRIX to use RMT Channel-0 Output (=signal 87)
REG_SET_FIELD(GPIO_FUNC0_OUT_SEL_CFG_REG+4*pin,GPIO_FUNC0_OEN_SEL,1); // use GPIO_ENABLE_REG of pin (not RMT) to enable this channel
REG_WRITE(GPIO_ENABLE_W1TC_REG,1<<pin); // disable output on pin - enable only when started
config.rmt_mode=RMT_MODE_TX;
config.tx_config.carrier_en=false;
config.channel=RMT_CHANNEL_0;
config.clk_div = 1;
config.mem_block_num=1;
config.gpio_num=(gpio_num_t)pin;
ESP_ERROR_CHECK(rmt_config(&config));
ESP_ERROR_CHECK(rmt_driver_install(config.channel,0,0));
rmt_set_source_clk(RMT_CHANNEL_0,RMT_BASECLK_REF);
}
///////////////////
void RFControl::start(uint8_t _numCycles, uint8_t tickTime){
void RFControl::start(uint8_t nCycles, uint8_t tickTime){ // starts transmission of pulses from internal data structure, repeated for nCycles, where each tick in pulse is tickTime microseconds long
start(data.data(), data.size(), nCycles, tickTime);
}
if(pCount%2==0) // if next entry is lower 16 bits of 32-bit memory
pRMT[pCount/2]=0; // set memory to zero (end-marker)
else
pRMT[pCount/2]&=0xFFFF; // else preserve lower 16 bits and zero our upper 16 bits
///////////////////
REG_WRITE(GPIO_ENABLE_W1TS_REG,1<<pin); // enable output on pin
numCycles=_numCycles; // set number of cycles to repeat transmission
REG_SET_FIELD(RMT_CH0CONF0_REG,RMT_DIV_CNT_CH0,tickTime); // set one tick = 1 microsecond * tickTime (RMT will be set to use 1 MHz REF_TICK, not 80 MHz APB_CLK)
REG_WRITE(RMT_CH0CONF1_REG,0x0000000D); // use REF_TICK clock; reset xmit and receive memory address to start of channel; START TRANSMITTING!
while(numCycles); // wait while transmission in progress
REG_WRITE(GPIO_ENABLE_W1TC_REG,1<<pin); // disable output on pin
void RFControl::start(uint32_t *data, int nData, uint8_t nCycles, uint8_t tickTime){ // starts transmission of pulses from specified data pointer, repeated for nCycles, where each tick in pulse is tickTime microseconds long
rmt_set_clk_div(RMT_CHANNEL_0,tickTime); // set clock divider
for(int i=0;i<nCycles;i++) // loop over nCycles
rmt_write_items(RMT_CHANNEL_0, (rmt_item32_t *) data, nData, true); // start transmission and wait until completed before returning
}
///////////////////
void RFControl::clear(){
pCount=0;
data.clear();
}
///////////////////
@ -62,42 +55,18 @@ void RFControl::add(uint16_t onTime, uint16_t offTime){
///////////////////
void RFControl::phase(uint16_t numTicks, uint8_t phase){
void RFControl::phase(uint16_t nTicks, uint8_t phase){
if(pCount==1023){ // maximum number of entries reached (saving one space for end-marker)
Serial.print("\n*** ERROR: Can't add more than 1023 entries to RF Control Module\n\n");
} else
uint32_t ticks=nTicks&0x7FFF;
if(numTicks>32767 || numTicks<1){
Serial.print("\n*** ERROR: Request to add RF Control entry with numTicks=");
Serial.print(numTicks);
Serial.print(" is out of allowable range: 1-32767\n\n");
} else {
int index=pCount/2;
if(pCount%2==0)
pRMT[index]=numTicks | (phase?(1<<15):0); // load entry into lower 16 bits of 32-bit memory
else
pRMT[index]=pRMT[index] & 0xFFFF | (numTicks<<16) | (phase?(1<<31):0); // load entry into upper 16 bits of 32-bit memory, preserving lower 16 bits
pCount++;
}
if(lowWord)
data.push_back(ticks | (phase?(1<<15):0));
else
data.back()|=ticks<<16 | (phase?(1<<31):0);
lowWord=!lowWord;
}
///////////////////
void RFControl::eot_int(void *arg){
numCycles--;
REG_WRITE(RMT_INT_CLR_REG,~0); // interrupt MUST be cleared first; transmission re-started after (clearing after restart crestes havoc)
if(numCycles)
REG_WRITE(RMT_CH0CONF1_REG,0x0000000D); // use REF_TICK clock; reset xmit and receive memory address to start of channel; re-start transmission
}
///////////////////
boolean RFControl::configured=false;
volatile int RFControl::numCycles;
//int32_t *RFControl::pRMT=(uint32_t *)RMT_CHANNEL_MEM(0);
int RFControl::pCount=0;
uint8_t RFControl::nChannels=0;

View File

@ -3,21 +3,30 @@
// RF Control Module //
////////////////////////////////////
#include "driver/rmt.h"
#include <vector>
using std::vector;
class RFControl {
private:
int pin;
static volatile int numCycles;
static boolean configured;
static uint32_t *pRMT;
static int pCount;
static void eot_int(void *arg);
rmt_config_t config;
vector<uint32_t> data;
boolean lowWord=true;
static uint8_t nChannels;
public:
RFControl(int pin); // creates transmitter on pin
static void clear(); // clears transmitter memory
static void add(uint16_t onTime, uint16_t offTime); // adds pulse of onTime ticks HIGH followed by offTime ticks LOW
static void phase(uint16_t numTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks
void start(uint8_t _numCycles, uint8_t tickTime=1); // starts transmission of pulses, repeated for numCycles, where each tick in pulse is tickTime microseconds long
RFControl(uint8_t pin); // creates transmitter on pin
void start(uint32_t *data, int nData, uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from specified data pointer, repeated for numCycles, where each tick in pulse is tickTime microseconds long
void start(uint8_t nCycles=1, uint8_t tickTime=1); // starts transmission of pulses from internal data structure, repeated for numCycles, where each tick in pulse is tickTime microseconds long
void clear(); // clears transmitter memory
void add(uint16_t onTime, uint16_t offTime); // adds pulse of onTime ticks HIGH followed by offTime ticks LOW
void phase(uint16_t nTicks, uint8_t phase); // adds either a HIGH phase or LOW phase lasting numTicks ticks
};
// Helper macro for creating your own storage of uint32_t data array elements - used with first variation of start() above
#define RF_PULSE(highTicks,lowTicks) (1 << 15 | highTicks | lowTicks << 16)

View File

@ -1,30 +1,83 @@
/* HomeSpan Remote Control Example */
// This is a placeholder .ino file that allows you to easily edit the contents of this library using the Arduino IDE,
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
#include "RFControl.h" // include RF Control Library
#include "PwmPin.h"
void setup() {
void setup(){
Serial.begin(115200); // start the Serial interface
Serial.flush();
delay(1000); // wait for interface to flush
Serial.begin(115200);
delay(1000);
Serial.print("\n\nHomeSpan RF Transmitter Example\n\n");
Serial.print("\n\nTest sketch for HomeSpan Extras Library\n\n");
RFControl rf(17); // create an instance of RFControl with signal output to pin 17 of the ESP32
Serial.println("Starting...");
// rf.phase(1000,HIGH);
// rf.phase(9000,LOW);
// rf.phase(1000,HIGH);
// rf.phase(9000,LOW);
// rf.phase(1000,HIGH);
// rf.phase(30000,LOW);
LedPin *led[20];
// rf.add(1000,9000); // create a pulse train with three 5000-tick high/low pulses
// rf.add(1000,9000); // create a pulse train with three 5000-tick high/low pulses
// rf.add(1000,9000); // create a pulse train with three 5000-tick high/low pulses
// rf.add(1000,30000); // create a pulse train with three 5000-tick high/low pulses
//
// rf.start(2,100);
// Serial.println("Done");
// while(1);
// uint8_t p[]={33,27,4,32,18,19,16,17,5}; // ESP32 test
uint8_t p[]={11,7,3,1,38,33,9,10}; // ESP32-S2 test
//
//#define NPOINTS 3
//
// uint32_t data[NPOINTS];
//
// for(int i=0;i<NPOINTS;i++){
// if(i<NPOINTS-1)
// data[i]=RF_PULSE(1000,9000);
// else
// data[i]=RF_PULSE(1000,30000);
//
// Serial.println((uint32_t)data[i],HEX);
// }
//
// rf.start(data,NPOINTS,1,100);
//
// Serial.println("Done.");
// while(1);
for(int i=0;i<sizeof(p);i++)
led[i]=new LedPin(p[i],20,5000);
led[7]->set(100);
rf.clear(); // clear the pulse train memory buffer
while(1);
}
rf.add(5000,5000); // create a pulse train with three 5000-tick high/low pulses
rf.add(5000,5000);
rf.add(5000,10000); // double duration of final low period
Serial.print("Starting 4 cycles of three 500 ms on pulses...");
rf.start(4,100); // start transmission of 4 cycles of the pulse train with 1 tick=100 microseconds
Serial.print("Done!\n");
delay(2000);
rf.clear();
for(int i=1000;i<10000;i+=1000)
rf.add(i,10000-i);
rf.add(10000,10000);
Serial.print("Starting 3 cycles of 100-1000 ms pulses...");
rf.start(3,100); // start transmission of 3 cycles of the pulse train with 1 tick=100 microseconds
Serial.print("Done!\n");
Serial.print("\nEnd Example");
} // end of setup()
void loop(){
}
} // end of loop()