9 #if CONFIG_IDF_TARGET_ESP32 == 0
10 #error Target is not ESP32!
14 #include "freertos/FreeRTOS.h"
15 #include "freertos/task.h"
16 #include "esp32/rom/gpio.h"
18 #include "soc/dport_reg.h"
19 #include "soc/spi_reg.h"
20 #include "soc/spi_struct.h"
21 #include "driver/gpio.h"
22 #include "hal/gpio_hal.h"
23 #include "esp_timer.h"
32 #define FALLING (0x02)
33 #define NOP() asm volatile ("nop")
35 #define MATRIX_DETACH_OUT_SIG (0x100)
36 #define MATRIX_DETACH_IN_LOW_PIN (0x30)
39 #define ClkRegToFreq(reg) (apb_freq / (((reg)->clkdiv_pre + 1) * ((reg)->clkcnt_n + 1)))
47 uint32_t clkdiv_pre: 13;
48 uint32_t clk_equ_sysclk: 1;
52 uint32_t getApbFrequency() {
53 rtc_cpu_freq_config_t conf;
54 rtc_clk_cpu_freq_get_config(&conf);
56 if(conf.freq_mhz >= 80) {
60 return((conf.source_freq_mhz * MHZ) / conf.div);
63 uint32_t spiFrequencyToClockDiv(uint32_t freq) {
64 uint32_t apb_freq = getApbFrequency();
65 if(freq >= apb_freq) {
66 return SPI_CLK_EQU_SYSCLK;
69 const spiClk_t minFreqReg = { 0x7FFFF000 };
70 uint32_t minFreq = ClkRegToFreq((
spiClk_t*) &minFreqReg);
72 return minFreqReg.value;
82 int8_t calPreVari = -2;
86 while(calPreVari++ <= 1) {
87 calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
89 reg.clkdiv_pre = 0x1FFF;
90 }
else if(calPre <= 0) {
93 reg.clkdiv_pre = calPre;
95 reg.clkcnt_l = ((reg.clkcnt_n + 1) / 2);
96 calFreq = ClkRegToFreq(®);
97 if(calFreq == (int32_t) freq) {
98 memcpy(&bestReg, ®,
sizeof(bestReg));
100 }
else if(calFreq < (int32_t) freq) {
101 if(RADIOLIB_ABS(freq - calFreq) < RADIOLIB_ABS(freq - bestFreq)) {
103 memcpy(&bestReg, ®,
sizeof(bestReg));
107 if(calFreq == (int32_t) freq) {
112 return(bestReg.value);
122 EspHal(int8_t sck, int8_t miso, int8_t mosi)
123 :
RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING),
124 spiSCK(sck), spiMISO(miso), spiMOSI(mosi) {
139 void pinMode(uint32_t pin, uint32_t mode)
override {
140 if(pin == RADIOLIB_NC) {
144 gpio_hal_context_t gpiohal;
145 gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
147 gpio_config_t conf = {
148 .pin_bit_mask = (1ULL<<pin),
149 .mode = (gpio_mode_t)mode,
150 .pull_up_en = GPIO_PULLUP_DISABLE,
151 .pull_down_en = GPIO_PULLDOWN_DISABLE,
152 .intr_type = (gpio_int_type_t)gpiohal.dev->pin[pin].int_type,
158 if(pin == RADIOLIB_NC) {
162 gpio_set_level((gpio_num_t)pin, value);
166 if(pin == RADIOLIB_NC) {
170 return(gpio_get_level((gpio_num_t)pin));
173 void attachInterrupt(uint32_t interruptNum,
void (*interruptCb)(
void), uint32_t mode)
override {
174 if(interruptNum == RADIOLIB_NC) {
178 gpio_install_isr_service((
int)ESP_INTR_FLAG_IRAM);
179 gpio_set_intr_type((gpio_num_t)interruptNum, (gpio_int_type_t)(mode & 0x7));
183 gpio_isr_handler_add((gpio_num_t)interruptNum, (
void (*)(
void*))interruptCb, NULL);
187 if(interruptNum == RADIOLIB_NC) {
191 gpio_isr_handler_remove((gpio_num_t)interruptNum);
192 gpio_wakeup_disable((gpio_num_t)interruptNum);
193 gpio_set_intr_type((gpio_num_t)interruptNum, GPIO_INTR_DISABLE);
196 void delay(
unsigned long ms)
override {
197 vTaskDelay(ms / portTICK_PERIOD_MS);
201 uint64_t m = (uint64_t)esp_timer_get_time();
203 uint64_t e = (m + us);
205 while((uint64_t)esp_timer_get_time() > e) {
209 while((uint64_t)esp_timer_get_time() < e) {
216 return((
unsigned long)(esp_timer_get_time() / 1000ULL));
220 return((
unsigned long)(esp_timer_get_time()));
223 long pulseIn(uint32_t pin, uint32_t state,
unsigned long timeout)
override {
224 if(pin == RADIOLIB_NC) {
229 uint32_t start = this->
micros();
230 uint32_t curtick = this->
micros();
233 if((this->
micros() - curtick) > timeout) {
238 return(this->
micros() - start);
243 DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
244 DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
247 this->spi->slave.trans_done = 0;
248 this->spi->slave.val = 0;
249 this->spi->pin.val = 0;
250 this->spi->user.val = 0;
251 this->spi->user1.val = 0;
252 this->spi->ctrl.val = 0;
253 this->spi->ctrl1.val = 0;
254 this->spi->ctrl2.val = 0;
255 this->spi->clock.val = 0;
256 this->spi->user.usr_mosi = 1;
257 this->spi->user.usr_miso = 1;
258 this->spi->user.doutdin = 1;
259 for(uint8_t i = 0; i < 16; i++) {
260 this->spi->data_buf[i] = 0x00000000;
264 this->spi->pin.ck_idle_edge = 0;
265 this->spi->user.ck_out_edge = 0;
268 this->spi->ctrl.wr_bit_order = 0;
269 this->spi->ctrl.rd_bit_order = 0;
272 this->spi->clock.val = spiFrequencyToClockDiv(2000000);
275 this->
pinMode(this->spiSCK, OUTPUT);
276 this->
pinMode(this->spiMISO, INPUT);
277 this->
pinMode(this->spiMOSI, OUTPUT);
278 gpio_matrix_out(this->spiSCK, HSPICLK_OUT_IDX,
false,
false);
279 gpio_matrix_in(this->spiMISO, HSPIQ_OUT_IDX,
false);
280 gpio_matrix_out(this->spiMOSI, HSPID_IN_IDX,
false,
false);
288 uint8_t spiTransferByte(uint8_t b) {
289 this->spi->mosi_dlen.usr_mosi_dbitlen = 7;
290 this->spi->miso_dlen.usr_miso_dbitlen = 7;
291 this->spi->data_buf[0] = b;
292 this->spi->cmd.usr = 1;
293 while(this->spi->cmd.usr);
294 return(this->spi->data_buf[0] & 0xFF);
298 for(
size_t i = 0; i < len; i++) {
299 in[i] = this->spiTransferByte(out[i]);
309 gpio_matrix_out(this->spiSCK, MATRIX_DETACH_OUT_SIG,
false,
false);
310 gpio_matrix_in(this->spiMISO, MATRIX_DETACH_IN_LOW_PIN,
false);
311 gpio_matrix_out(this->spiMOSI, MATRIX_DETACH_OUT_SIG,
false,
false);
319 spi_dev_t * spi = (
volatile spi_dev_t *)(DR_REG_SPI2_BASE);
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override
Measure the length of incoming digital pulse in microseconds. Must be implemented by the platform-spe...
Definition: EspHal.h:223
void attachInterrupt(uint32_t interruptNum, void(*interruptCb)(void), uint32_t mode) override
Method to attach function to an external interrupt. Must be implemented by the platform-specific hard...
Definition: EspHal.h:173
unsigned long micros() override
Get number of microseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition: EspHal.h:219
uint32_t digitalRead(uint32_t pin) override
Digital read method. Must be implemented by the platform-specific hardware abstraction!
Definition: EspHal.h:165
void spiBeginTransaction()
Method to start SPI transaction.
Definition: EspHal.h:283
void spiEndTransaction()
Method to end SPI transaction.
Definition: EspHal.h:303
unsigned long millis() override
Get number of milliseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition: EspHal.h:215
void pinMode(uint32_t pin, uint32_t mode) override
GPIO pin mode (input/output/...) configuration method. Must be implemented by the platform-specific h...
Definition: EspHal.h:139
void detachInterrupt(uint32_t interruptNum) override
Method to detach function from an external interrupt. Must be implemented by the platform-specific ha...
Definition: EspHal.h:186
void delay(unsigned long ms) override
Blocking wait function. Must be implemented by the platform-specific hardware abstraction!
Definition: EspHal.h:196
void term() override
Module termination method. This will be called by all radio modules when the destructor is called....
Definition: EspHal.h:132
void delayMicroseconds(unsigned long us) override
Blocking microsecond wait function. Must be implemented by the platform-specific hardware abstraction...
Definition: EspHal.h:200
void digitalWrite(uint32_t pin, uint32_t value) override
Digital write method. Must be implemented by the platform-specific hardware abstraction!
Definition: EspHal.h:157
void init() override
Module initialization method. This will be called by all radio modules at the beginning of startup....
Definition: EspHal.h:127
void spiBegin()
SPI initialization method.
Definition: EspHal.h:241
void spiEnd()
SPI termination method.
Definition: EspHal.h:307
void spiTransfer(uint8_t *out, size_t len, uint8_t *in)
Method to transfer buffer over SPI.
Definition: EspHal.h:297
Hardware abstraction library base interface.
Definition: Hal.h:13
RadioLibHal(const uint32_t input, const uint32_t output, const uint32_t low, const uint32_t high, const uint32_t rising, const uint32_t falling)
Default constructor.
Definition: Hal.cpp:3