#include "RadiolibTactilityHal.h" #include "hal/gpio_hal.h" #include "esp_timer.h" constexpr const char* TAG = "RadiolibTactilityHal"; void RadiolibTactilityHal::init() { // we only need to init the SPI here spiBegin(); } void RadiolibTactilityHal::term() { // we only need to stop the SPI here spiEnd(); } void RadiolibTactilityHal::pinMode(uint32_t pin, uint32_t mode) { if(pin == RADIOLIB_NC) { return; } gpio_hal_context_t gpiohal; gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0); gpio_config_t conf = { .pin_bit_mask = (1ULL<pin[pin].int_type, }; gpio_config(&conf); } void RadiolibTactilityHal::digitalWrite(uint32_t pin, uint32_t value) { if(pin == RADIOLIB_NC) { return; } gpio_set_level((gpio_num_t)pin, value); } uint32_t RadiolibTactilityHal::digitalRead(uint32_t pin) { if(pin == RADIOLIB_NC) { return(0); } return(gpio_get_level((gpio_num_t)pin)); } void RadiolibTactilityHal::attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) { if(interruptNum == RADIOLIB_NC) { return; } gpio_install_isr_service((int)ESP_INTR_FLAG_IRAM); gpio_set_intr_type((gpio_num_t)interruptNum, (gpio_int_type_t)(mode & 0x7)); // this uses function typecasting, which is not defined when the functions have different signatures // untested and might not work gpio_isr_handler_add((gpio_num_t)interruptNum, (void (*)(void*))interruptCb, NULL); } void RadiolibTactilityHal::detachInterrupt(uint32_t interruptNum) { if(interruptNum == RADIOLIB_NC) { return; } gpio_isr_handler_remove((gpio_num_t)interruptNum); gpio_wakeup_disable((gpio_num_t)interruptNum); gpio_set_intr_type((gpio_num_t)interruptNum, GPIO_INTR_DISABLE); } void RadiolibTactilityHal::delay(unsigned long ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } void RadiolibTactilityHal::delayMicroseconds(unsigned long us) { uint64_t m = (uint64_t)esp_timer_get_time(); if(us) { uint64_t e = (m + us); if(m > e) { // overflow while((uint64_t)esp_timer_get_time() > e); } while((uint64_t)esp_timer_get_time() < e); } } unsigned long RadiolibTactilityHal::millis() { return((unsigned long)(esp_timer_get_time() / 1000ULL)); } unsigned long RadiolibTactilityHal::micros() { return((unsigned long)(esp_timer_get_time())); } long RadiolibTactilityHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) { if(pin == RADIOLIB_NC) { return(0); } this->pinMode(pin, GPIO_MODE_INPUT); uint32_t start = this->micros(); uint32_t curtick = this->micros(); while(this->digitalRead(pin) == state) { if((this->micros() - curtick) > timeout) { return(0); } } return(this->micros() - start); } void RadiolibTactilityHal::spiBegin() { if (!spiInitialized) { TT_LOG_I(TAG, "SPI Begin!"); spi_device_interface_config_t devcfg = {}; devcfg.clock_speed_hz = spiFrequency; devcfg.mode = 0; devcfg.spics_io_num = csPin; devcfg.queue_size = 1; esp_err_t ret = spi_bus_add_device(spiHostDevice, &devcfg, &spiDeviceHandle); if (ret != ESP_OK) { TT_LOG_E(TAG, "Failed to add SPI device: %s", esp_err_to_name(ret)); } spiInitialized = true; } } void RadiolibTactilityHal::spiBeginTransaction() { // This function is used to set up the transaction (speed, bit order, mode, ...). // With the ESP-IDF HAL this is automatically done, so no code needed. } void RadiolibTactilityHal::spiTransfer(uint8_t* out, size_t len, uint8_t* in) { spi_transaction_t t; auto lock = getLock()->asScopedLock(); bool locked = lock.lock(portMAX_DELAY); if (!locked) { TT_LOG_E(TAG, "Failed to aquire SPI lock"); } memset(&t, 0, sizeof(t)); // Zero out the transaction t.length = len * 8; // Length is in bits t.tx_buffer = out; // The data to send t.rx_buffer = in; // The data to receive spi_device_polling_transmit(spiDeviceHandle, &t); } void RadiolibTactilityHal::spiEndTransaction() { // nothing needs to be done here } void RadiolibTactilityHal::spiEnd() { if (spiInitialized) { spi_bus_remove_device(spiDeviceHandle); spiInitialized = false; } }