diff --git a/.vscode/settings.json b/.vscode/settings.json index 8a3cc7c..1ca7fe0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "C_Cpp.intelliSenseEngine": "default", - "idf.espIdfPath": "/home/bruno/esp/v5.4.1/esp-idf", + "idf.espIdfPath": "/home/bruno/esp/master/esp-idf", "idf.pythonInstallPath": "/usr/bin/python", "idf.openOcdConfigs": [ "board/esp32s3-builtin.cfg" @@ -29,6 +29,17 @@ "esp_mac.h": "c", "gpio.h": "c", "chrono": "c", - "cstdint": "c" + "cstdint": "c", + "task.h": "c", + "compare": "c", + "uart_struct.h": "c", + "uart.h": "c", + "gpio_num.h": "c", + "mcp3550.h": "c", + "esp_timer.h": "c", + "math.h": "c", + "esp_check.h": "c", + "radio.h": "c", + "sx1262.h": "c" } } diff --git a/components/ra01s/CMakeLists.txt b/components/ra01s/CMakeLists.txt deleted file mode 100644 index b81d5ac..0000000 --- a/components/ra01s/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(component_srcs "ra01s.c") - -idf_component_register(SRCS "${component_srcs}" - PRIV_REQUIRES driver - INCLUDE_DIRS ".") diff --git a/components/ra01s/Kconfig.projbuild b/components/ra01s/Kconfig.projbuild deleted file mode 100644 index 5ed4171..0000000 --- a/components/ra01s/Kconfig.projbuild +++ /dev/null @@ -1,163 +0,0 @@ -menu "SX126X Configuration" - - config GPIO_RANGE_MAX - int - default 33 if IDF_TARGET_ESP32 - default 46 if IDF_TARGET_ESP32S2 - default 48 if IDF_TARGET_ESP32S3 - default 18 if IDF_TARGET_ESP32C2 - default 19 if IDF_TARGET_ESP32C3 - default 30 if IDF_TARGET_ESP32C6 - - choice FREQUENCY - prompt "Frequency to use" - default 433MHZ - help - Select Frequency to use. - config 433MHZ - bool "433MHz" - help - Frequency is 433MHz. - config 866MHZ - bool "866MHz" - help - Frequency is 866MHz. - config 915MHZ - bool "915MHz" - help - Frequency is 915MHz. - config OTHER - bool "Other" - help - Other Frequency. - endchoice - - config OTHER_FREQUENCY - depends on OTHER - int "Frequency to use[MHz]" - range 1 999 - default 433 - help - Frequency to use[MHz]. - - config ADVANCED - bool "Enable Advanced settings" - default false - help - Enable Advanced settings. - - config CODING_RATE - depends on ADVANCED - int "Error coding rate" - range 1 4 - default 1 - help - Error coding rate. - - config BANDWIDTH - depends on ADVANCED - int "Signal Bandwidth" - range 0 6 - default 4 - help - Signal Bandwidth. - - config SF_RATE - depends on ADVANCED - int "Spreading Factor" - range 5 12 - default 7 - help - Spreading Factor. - - config USE_TCXO - bool "Enable TCXO" - default false - help - Enable Temperature-Compensated Crystal Oscillator. - - config MISO_GPIO - int "SX126X MISO GPIO" - range 0 GPIO_RANGE_MAX - default 19 if IDF_TARGET_ESP32 - default 37 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 4 # C3 and others - help - Pin Number to be used as the MISO SPI signal. - - config SCLK_GPIO - int "SX126X SCLK GPIO" - range 0 GPIO_RANGE_MAX - default 18 if IDF_TARGET_ESP32 - default 36 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 5 # C3 and others - help - Pin Number to be used as the SCLK SPI signal. - - config MOSI_GPIO - int "SX126X MOSI GPIO" - range 0 GPIO_RANGE_MAX - default 23 if IDF_TARGET_ESP32 - default 35 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 6 # C3 and others - help - Pin Number to be used as the MOSI SPI signal. - - config NSS_GPIO - int "SX126X NSS GPIO" - range 0 GPIO_RANGE_MAX - default 15 if IDF_TARGET_ESP32 - default 34 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 7 # C3 and others - help - Pin Number to be used as the NSS SPI signal. - - config RST_GPIO - int "SX126X RST GPIO" - range 0 GPIO_RANGE_MAX - default 16 if IDF_TARGET_ESP32 - default 38 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 2 # C3 and others - help - Pin Number to be used as the RST signal. - - config BUSY_GPIO - int "SX126X BUSY GPIO" - range 0 GPIO_RANGE_MAX - default 17 if IDF_TARGET_ESP32 - default 39 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - default 3 # C3 and others - help - Pin Number to be used as the BUSY signal. - - config TXEN_GPIO - int "SX126X TXEN GPIO" - range -1 GPIO_RANGE_MAX - default -1 - help - Pin Number to be used as the TXEN signal. - - config RXEN_GPIO - int "SX126X RXEN GPIO" - range -1 GPIO_RANGE_MAX - default -1 - help - Pin Number to be used as the RXEN signal. - - choice SPI_HOST - prompt "SPI peripheral that controls this bus" - default SPI2_HOST - help - Select SPI peripheral that controls this bus. - config SPI2_HOST - bool "SPI2_HOST" - help - Use SPI2_HOST. This is also called HSPI_HOST. - config SPI3_HOST - depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - bool "SPI3_HOST" - help - USE SPI3_HOST. This is also called VSPI_HOST - endchoice - -endmenu diff --git a/components/ra01s/ra01s.c b/components/ra01s/ra01s.c deleted file mode 100755 index 5f44b78..0000000 --- a/components/ra01s/ra01s.c +++ /dev/null @@ -1,1021 +0,0 @@ -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include -#include -#include "esp_log.h" - -#include "ra01s.h" - -#define TAG "RA01S" - -// SPI Stuff -#if CONFIG_SPI2_HOST -#define HOST_ID SPI2_HOST -#elif CONFIG_SPI3_HOST -#define HOST_ID SPI3_HOST -#endif - -static spi_device_handle_t SpiHandle; - -// Global Stuff -static uint8_t PacketParams[6]; -static bool txActive; -static int txLost = 0; -static bool debugPrint; -static int SX126x_SPI_SELECT; -static int SX126x_RESET; -static int SX126x_BUSY; -static int SX126x_TXEN; -static int SX126x_RXEN; - -// Arduino compatible macros -#define delayMicroseconds(us) esp_rom_delay_us(us) -#define delay(ms) esp_rom_delay_us(ms*1000) - - -void LoRaErrorDefault(int error) -{ - if (debugPrint) { - ESP_LOGE(TAG, "LoRaErrorDefault=%d", error); - } - while (true) { - vTaskDelay(1); - } -} - -__attribute__ ((weak, alias ("LoRaErrorDefault"))) void LoRaError(int error); - - -void LoRaInit(void) -{ - ESP_LOGI(TAG, "CONFIG_MISO_GPIO=%d", CONFIG_MISO_GPIO); - ESP_LOGI(TAG, "CONFIG_MOSI_GPIO=%d", CONFIG_MOSI_GPIO); - ESP_LOGI(TAG, "CONFIG_SCLK_GPIO=%d", CONFIG_SCLK_GPIO); - ESP_LOGI(TAG, "CONFIG_NSS_GPIO=%d", CONFIG_NSS_GPIO); - ESP_LOGI(TAG, "CONFIG_RST_GPIO=%d", CONFIG_RST_GPIO); - ESP_LOGI(TAG, "CONFIG_BUSY_GPIO=%d", CONFIG_BUSY_GPIO); - ESP_LOGI(TAG, "CONFIG_TXEN_GPIO=%d", CONFIG_TXEN_GPIO); - ESP_LOGI(TAG, "CONFIG_RXEN_GPIO=%d", CONFIG_RXEN_GPIO); - - SX126x_SPI_SELECT = CONFIG_NSS_GPIO; - SX126x_RESET = CONFIG_RST_GPIO; - SX126x_BUSY = CONFIG_BUSY_GPIO; - SX126x_TXEN = CONFIG_TXEN_GPIO; - SX126x_RXEN = CONFIG_RXEN_GPIO; - - txActive = false; - debugPrint = false; - - gpio_reset_pin(SX126x_SPI_SELECT); - gpio_set_direction(SX126x_SPI_SELECT, GPIO_MODE_OUTPUT); - gpio_set_level(SX126x_SPI_SELECT, 1); - - gpio_reset_pin(SX126x_RESET); - gpio_set_direction(SX126x_RESET, GPIO_MODE_OUTPUT); - - gpio_reset_pin(SX126x_BUSY); - gpio_set_direction(SX126x_BUSY, GPIO_MODE_INPUT); - - if (SX126x_TXEN != -1) { - gpio_reset_pin(SX126x_TXEN); - gpio_set_direction(SX126x_TXEN, GPIO_MODE_OUTPUT); - } - - if (SX126x_RXEN != -1) { - gpio_reset_pin(SX126x_RXEN); - gpio_set_direction(SX126x_RXEN, GPIO_MODE_OUTPUT); - } - - spi_bus_config_t spi_bus_config = { - .sclk_io_num = CONFIG_SCLK_GPIO, - .mosi_io_num = CONFIG_MOSI_GPIO, - .miso_io_num = CONFIG_MISO_GPIO, - .quadwp_io_num = -1, - .quadhd_io_num = -1 - }; - - esp_err_t ret; - ret = spi_bus_initialize( HOST_ID, &spi_bus_config, SPI_DMA_CH_AUTO ); - ESP_LOGI(TAG, "spi_bus_initialize=%d",ret); - assert(ret==ESP_OK); - - spi_device_interface_config_t devcfg = { - .clock_speed_hz = 9000000, - .mode = 0, - .spics_io_num = CONFIG_NSS_GPIO, - .queue_size = 7, - .flags = 0, - .pre_cb = NULL - }; - //spi_device_handle_t handle; - ret = spi_bus_add_device( HOST_ID, &devcfg, &SpiHandle); - ESP_LOGI(TAG, "spi_bus_add_device=%d",ret); - assert(ret==ESP_OK); -} - -void spi_write_byte(uint8_t* Dataout, size_t DataLength ) -{ - spi_transaction_t SPITransaction; - - if ( DataLength > 0 ) { - memset( &SPITransaction, 0, sizeof( spi_transaction_t ) ); - SPITransaction.length = DataLength * 8; - SPITransaction.tx_buffer = Dataout; - SPITransaction.rx_buffer = NULL; - spi_device_transmit( SpiHandle, &SPITransaction ); - } - - return; -} - -void spi_read_byte(uint8_t* Datain, uint8_t* Dataout, size_t DataLength ) -{ - spi_transaction_t SPITransaction; - - if ( DataLength > 0 ) { - memset( &SPITransaction, 0, sizeof( spi_transaction_t ) ); - SPITransaction.length = DataLength * 8; - SPITransaction.tx_buffer = Dataout; - SPITransaction.rx_buffer = Datain; - spi_device_transmit( SpiHandle, &SPITransaction ); - } - - return; -} - -uint8_t spi_transfer(uint8_t address) -{ - uint8_t datain[1]; - uint8_t dataout[1]; - dataout[0] = address; - //spi_write_byte(dataout, 1 ); - spi_read_byte(datain, dataout, 1 ); - return datain[0]; -} - - -int16_t LoRaBegin(uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, bool useRegulatorLDO) -{ - if ( txPowerInDbm > 22 ) - txPowerInDbm = 22; - if ( txPowerInDbm < -3 ) - txPowerInDbm = -3; - - Reset(); - - uint8_t wk[2]; - ReadRegister(SX126X_REG_LORA_SYNC_WORD_MSB, wk, 2); // 0x0740 - uint16_t syncWord = (wk[0] << 8) + wk[1]; - ESP_LOGI(TAG, "syncWord=0x%x", syncWord); - if (syncWord != SX126X_SYNC_WORD_PUBLIC && syncWord != SX126X_SYNC_WORD_PRIVATE) { - ESP_LOGE(TAG, "SX126x error, maybe no SPI connection"); - return ERR_INVALID_MODE; - } - - ESP_LOGI(TAG, "SX126x installed"); - SetStandby(SX126X_STANDBY_RC); - - SetDio2AsRfSwitchCtrl(true); - ESP_LOGI(TAG, "tcxoVoltage=%f", tcxoVoltage); - // set TCXO control, if requested - if(tcxoVoltage > 0.0) { - SetDio3AsTcxoCtrl(tcxoVoltage, RADIO_TCXO_SETUP_TIME); // Configure the radio to use a TCXO controlled by DIO3 - } - - Calibrate( SX126X_CALIBRATE_IMAGE_ON - | SX126X_CALIBRATE_ADC_BULK_P_ON - | SX126X_CALIBRATE_ADC_BULK_N_ON - | SX126X_CALIBRATE_ADC_PULSE_ON - | SX126X_CALIBRATE_PLL_ON - | SX126X_CALIBRATE_RC13M_ON - | SX126X_CALIBRATE_RC64K_ON - ); - - ESP_LOGI(TAG, "useRegulatorLDO=%d", useRegulatorLDO); - if (useRegulatorLDO) { - SetRegulatorMode(SX126X_REGULATOR_LDO); // set regulator mode: LDO - } else { - SetRegulatorMode(SX126X_REGULATOR_DC_DC); // set regulator mode: DC-DC - } - - SetBufferBaseAddress(0, 0); -#if 0 - // SX1261_TRANCEIVER - SetPaConfig(0x06, 0x00, 0x01, 0x01); // PA Optimal Settings +15 dBm - // SX1262_TRANCEIVER - SetPaConfig(0x04, 0x07, 0x00, 0x01); // PA Optimal Settings +22 dBm - // SX1268_TRANCEIVER - SetPaConfig(0x04, 0x07, 0x00, 0x01); // PA Optimal Settings +22 dBm -#endif - SetPaConfig(0x04, 0x07, 0x00, 0x01); // PA Optimal Settings +22 dBm - SetOvercurrentProtection(60.0); // current max 60mA for the whole device - SetPowerConfig(txPowerInDbm, SX126X_PA_RAMP_200U); //0 fuer Empfaenger - SetRfFrequency(frequencyInHz); - return ERR_NONE; -} - -void FixInvertedIQ(uint8_t iqConfig) -{ - // fixes IQ configuration for inverted IQ - // see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.4 for details - // When exchanging LoRa packets with inverted IQ polarity, some packet losses may be observed for longer packets. - // Workaround: Bit 2 at address 0x0736 must be set to: - // “0” when using inverted IQ polarity (see the SetPacketParam(...) command) - // “1” when using standard IQ polarity - - // read current IQ configuration - uint8_t iqConfigCurrent = 0; - ReadRegister(SX126X_REG_IQ_POLARITY_SETUP, &iqConfigCurrent, 1); // 0x0736 - - // set correct IQ configuration - //if(iqConfig == SX126X_LORA_IQ_STANDARD) { - if(iqConfig == SX126X_LORA_IQ_INVERTED) { - iqConfigCurrent &= 0xFB; // using inverted IQ polarity - } else { - iqConfigCurrent |= 0x04; // using standard IQ polarity - } - - // update with the new value - WriteRegister(SX126X_REG_IQ_POLARITY_SETUP, &iqConfigCurrent, 1); // 0x0736 -} - - -void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, bool crcOn, bool invertIrq) -{ - SetStopRxTimerOnPreambleDetect(false); - SetLoRaSymbNumTimeout(0); - SetPacketType(SX126X_PACKET_TYPE_LORA); // SX126x.ModulationParams.PacketType : MODEM_LORA - uint8_t ldro = 0; // LowDataRateOptimize OFF - SetModulationParams(spreadingFactor, bandwidth, codingRate, ldro); - - PacketParams[0] = (preambleLength >> 8) & 0xFF; - PacketParams[1] = preambleLength; - if ( payloadLen ) - { - PacketParams[2] = 0x01; // Fixed length packet (implicit header) - PacketParams[3] = payloadLen; - } - else - { - PacketParams[2] = 0x00; // Variable length packet (explicit header) - PacketParams[3] = 0xFF; - } - - if ( crcOn ) - PacketParams[4] = SX126X_LORA_CRC_ON; - else - PacketParams[4] = SX126X_LORA_CRC_OFF; - - if ( invertIrq ) - PacketParams[5] = 0x01; // Inverted LoRa I and Q signals setup - else - PacketParams[5] = 0x00; // Standard LoRa I and Q signals setup - - // fixes IQ configuration for inverted IQ - FixInvertedIQ(PacketParams[5]); - - WriteCommand(SX126X_CMD_SET_PACKET_PARAMS, PacketParams, 6); // 0x8C - - // Do not use DIO interruptst - SetDioIrqParams(SX126X_IRQ_ALL, //all interrupts enabled - SX126X_IRQ_NONE, //interrupts on DIO1 - SX126X_IRQ_NONE, //interrupts on DIO2 - SX126X_IRQ_NONE //interrupts on DIO3 - ); - - // Receive state no receive timeoout - SetRx(0xFFFFFF); -} - - -void LoRaDebugPrint(bool enable) -{ - debugPrint = enable; -} - - -uint8_t LoRaReceive(uint8_t *pData, int16_t len) -{ - uint8_t rxLen = 0; - uint16_t irqRegs = GetIrqStatus(); - //uint8_t status = GetStatus(); - - if( irqRegs & SX126X_IRQ_RX_DONE ) - { - //ClearIrqStatus(SX126X_IRQ_RX_DONE); - ClearIrqStatus(SX126X_IRQ_ALL); - rxLen = ReadBuffer(pData, len); - } - - return rxLen; -} - - -bool LoRaSend(uint8_t *pData, int16_t len, uint8_t mode) -{ - uint16_t irqStatus; - bool rv = false; - - if ( txActive == false ) - { - txActive = true; - if (PacketParams[2] == 0x00) { // Variable length packet (explicit header) - PacketParams[3] = len; - } - WriteCommand(SX126X_CMD_SET_PACKET_PARAMS, PacketParams, 6); // 0x8C - - //ClearIrqStatus(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT); - ClearIrqStatus(SX126X_IRQ_ALL); - - WriteBuffer(pData, len); - SetTx(500); - - if ( mode & SX126x_TXMODE_SYNC ) - { - irqStatus = GetIrqStatus(); - while ( (!(irqStatus & SX126X_IRQ_TX_DONE)) && (!(irqStatus & SX126X_IRQ_TIMEOUT)) ) - { - delay(1); - irqStatus = GetIrqStatus(); - } - if (debugPrint) { - ESP_LOGI(TAG, "irqStatus=0x%x", irqStatus); - if (irqStatus & SX126X_IRQ_TX_DONE) { - ESP_LOGI(TAG, "SX126X_IRQ_TX_DONE"); - } - if (irqStatus & SX126X_IRQ_TIMEOUT) { - ESP_LOGI(TAG, "SX126X_IRQ_TIMEOUT"); - } - } - txActive = false; - - SetRx(0xFFFFFF); - - if ( irqStatus & SX126X_IRQ_TX_DONE) { - rv = true; - } - } - else - { - rv = true; - } - } - if (debugPrint) { - ESP_LOGI(TAG, "Send rv=0x%x", rv); - } - if (rv == false) txLost++; - return rv; -} - - -bool ReceiveMode(void) -{ - uint16_t irq; - bool rv = false; - - if ( txActive == false ) - { - rv = true; - } - else - { - irq = GetIrqStatus(); - if ( irq & (SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT) ) - { - SetRx(0xFFFFFF); - txActive = false; - rv = true; - } - } - - return rv; -} - - -void GetPacketStatus(int8_t *rssiPacket, int8_t *snrPacket) -{ - uint8_t buf[4]; - ReadCommand( SX126X_CMD_GET_PACKET_STATUS, buf, 4 ); // 0x14 - *rssiPacket = (buf[3] >> 1) * -1; - ( buf[2] < 128 ) ? ( *snrPacket = buf[2] >> 2 ) : ( *snrPacket = ( ( buf[2] - 256 ) >> 2 ) ); -} - - -void SetTxPower(int8_t txPowerInDbm) -{ - SetPowerConfig(txPowerInDbm, SX126X_PA_RAMP_200U); -} - - -void Reset(void) -{ - delay(10); - gpio_set_level(SX126x_RESET,0); - delay(20); - gpio_set_level(SX126x_RESET,1); - delay(10); - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "Reset", true); -} - - -void Wakeup(void) -{ - GetStatus(); -} - - -void SetStandby(uint8_t mode) -{ - uint8_t data = mode; - WriteCommand(SX126X_CMD_SET_STANDBY, &data, 1); // 0x80 -} - - -uint8_t GetStatus(void) -{ - uint8_t rv; - ReadCommand(SX126X_CMD_GET_STATUS, &rv, 1); // 0xC0 - return rv; -} - - -void SetDio3AsTcxoCtrl(float voltage, uint32_t delay) -{ - uint8_t buf[4]; - - //buf[0] = tcxoVoltage & 0x07; - if(fabs(voltage - 1.6) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_1_6; - } else if(fabs(voltage - 1.7) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_1_7; - } else if(fabs(voltage - 1.8) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_1_8; - } else if(fabs(voltage - 2.2) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_2_2; - } else if(fabs(voltage - 2.4) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_2_4; - } else if(fabs(voltage - 2.7) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_2_7; - } else if(fabs(voltage - 3.0) <= 0.001) { - buf[0] = SX126X_DIO3_OUTPUT_3_0; - } else { - buf[0] = SX126X_DIO3_OUTPUT_3_3; - } - - uint32_t delayValue = (float)delay / 15.625; - buf[1] = ( uint8_t )( ( delayValue >> 16 ) & 0xFF ); - buf[2] = ( uint8_t )( ( delayValue >> 8 ) & 0xFF ); - buf[3] = ( uint8_t )( delayValue & 0xFF ); - - WriteCommand(SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, buf, 4); // 0x97 -} - - -void Calibrate(uint8_t calibParam) -{ - uint8_t data = calibParam; - WriteCommand(SX126X_CMD_CALIBRATE, &data, 1); // 0x89 -} - - -void SetDio2AsRfSwitchCtrl(uint8_t enable) -{ - uint8_t data = enable; - WriteCommand(SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, &data, 1); // 0x9D -} - - -void SetRfFrequency(uint32_t frequency) -{ - uint8_t buf[4]; - uint32_t freq = 0; - - CalibrateImage(frequency); - - freq = (uint32_t)((double)frequency / (double)FREQ_STEP); - buf[0] = (uint8_t)((freq >> 24) & 0xFF); - buf[1] = (uint8_t)((freq >> 16) & 0xFF); - buf[2] = (uint8_t)((freq >> 8) & 0xFF); - buf[3] = (uint8_t)(freq & 0xFF); - WriteCommand(SX126X_CMD_SET_RF_FREQUENCY, buf, 4); // 0x86 -} - - -void CalibrateImage(uint32_t frequency) -{ - uint8_t calFreq[2]; - - if( frequency> 900000000 ) - { - calFreq[0] = 0xE1; - calFreq[1] = 0xE9; - } - else if( frequency > 850000000 ) - { - calFreq[0] = 0xD7; - calFreq[1] = 0xDB; - } - else if( frequency > 770000000 ) - { - calFreq[0] = 0xC1; - calFreq[1] = 0xC5; - } - else if( frequency > 460000000 ) - { - calFreq[0] = 0x75; - calFreq[1] = 0x81; - } - else if( frequency > 425000000 ) - { - calFreq[0] = 0x6B; - calFreq[1] = 0x6F; - } - WriteCommand(SX126X_CMD_CALIBRATE_IMAGE, calFreq, 2); // 0x98 -} - - -void SetRegulatorMode(uint8_t mode) -{ - uint8_t data = mode; - WriteCommand(SX126X_CMD_SET_REGULATOR_MODE, &data, 1); // 0x96 -} - - -void SetBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) -{ - uint8_t buf[2]; - - buf[0] = txBaseAddress; - buf[1] = rxBaseAddress; - WriteCommand(SX126X_CMD_SET_BUFFER_BASE_ADDRESS, buf, 2); // 0x8F -} - - -void SetPowerConfig(int8_t power, uint8_t rampTime) -{ - uint8_t buf[2]; - - if( power > 22 ) - { - power = 22; - } - else if( power < -3 ) - { - power = -3; - } - - buf[0] = power; - buf[1] = ( uint8_t )rampTime; - WriteCommand(SX126X_CMD_SET_TX_PARAMS, buf, 2); // 0x8E -} - - -void SetPaConfig(uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut) -{ - uint8_t buf[4]; - - buf[0] = paDutyCycle; - buf[1] = hpMax; - buf[2] = deviceSel; - buf[3] = paLut; - WriteCommand(SX126X_CMD_SET_PA_CONFIG, buf, 4); // 0x95 -} - - -void SetOvercurrentProtection(float currentLimit) -{ - if((currentLimit >= 0.0) && (currentLimit <= 140.0)) { - uint8_t buf[1]; - buf[0] = (uint8_t)(currentLimit / 2.5); - WriteRegister(SX126X_REG_OCP_CONFIGURATION, buf, 1); // 0x08E7 - } -} - -void SetSyncWord(int16_t sync) { - uint8_t buf[2]; - - buf[0] = (uint8_t)((sync >> 8) & 0x00FF); - buf[1] = (uint8_t)(sync & 0x00FF); - WriteRegister(SX126X_REG_LORA_SYNC_WORD_MSB, buf, 2); // 0x0740 -} - -void SetDioIrqParams -( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) -{ - uint8_t buf[8]; - - buf[0] = (uint8_t)((irqMask >> 8) & 0x00FF); - buf[1] = (uint8_t)(irqMask & 0x00FF); - buf[2] = (uint8_t)((dio1Mask >> 8) & 0x00FF); - buf[3] = (uint8_t)(dio1Mask & 0x00FF); - buf[4] = (uint8_t)((dio2Mask >> 8) & 0x00FF); - buf[5] = (uint8_t)(dio2Mask & 0x00FF); - buf[6] = (uint8_t)((dio3Mask >> 8) & 0x00FF); - buf[7] = (uint8_t)(dio3Mask & 0x00FF); - WriteCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, buf, 8); // 0x08 -} - - -void SetStopRxTimerOnPreambleDetect(bool enable) -{ - ESP_LOGI(TAG, "SetStopRxTimerOnPreambleDetect enable=%d", enable); - //uint8_t data = (uint8_t)enable; - uint8_t data = 0; - if (enable) data = 1; - WriteCommand(SX126X_CMD_STOP_TIMER_ON_PREAMBLE, &data, 1); // 0x9F -} - - -void SetLoRaSymbNumTimeout(uint8_t SymbNum) -{ - uint8_t data = SymbNum; - WriteCommand(SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT, &data, 1); // 0xA0 -} - - -void SetPacketType(uint8_t packetType) -{ - uint8_t data = packetType; - WriteCommand(SX126X_CMD_SET_PACKET_TYPE, &data, 1); // 0x01 -} - - -void SetModulationParams(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize) -{ - uint8_t data[4]; - //currently only LoRa supported - data[0] = spreadingFactor; - data[1] = bandwidth; - data[2] = codingRate; - data[3] = lowDataRateOptimize; - WriteCommand(SX126X_CMD_SET_MODULATION_PARAMS, data, 4); // 0x8B -} - - -void SetCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout) -{ - uint8_t data[7]; - data[0] = cadSymbolNum; - data[1] = cadDetPeak; - data[2] = cadDetMin; - data[3] = cadExitMode; - data[4] = (uint8_t)((cadTimeout >> 16) & 0xFF); - data[5] = (uint8_t)((cadTimeout >> 8) & 0xFF); - data[6] = (uint8_t)(cadTimeout & 0xFF); - WriteCommand(SX126X_CMD_SET_CAD_PARAMS, data, 7); // 0x88 -} - - -void SetCad() -{ - uint8_t data = 0; - WriteCommand(SX126X_CMD_SET_CAD, &data, 0); // 0xC5 -} - - -uint16_t GetIrqStatus( void ) -{ - uint8_t data[3]; - ReadCommand(SX126X_CMD_GET_IRQ_STATUS, data, 3); // 0x12 - return (data[1] << 8) | data[2]; -} - - -void ClearIrqStatus(uint16_t irq) -{ - uint8_t buf[2]; - - buf[0] = (uint8_t)(((uint16_t)irq >> 8) & 0x00FF); - buf[1] = (uint8_t)((uint16_t)irq & 0x00FF); - WriteCommand(SX126X_CMD_CLEAR_IRQ_STATUS, buf, 2); // 0x02 -} - - -void SetRx(uint32_t timeout) -{ - if (debugPrint) { - ESP_LOGI(TAG, "----- SetRx timeout=%"PRIu32, timeout); - } - SetStandby(SX126X_STANDBY_RC); - SetRxEnable(); - uint8_t buf[3]; - buf[0] = (uint8_t)((timeout >> 16) & 0xFF); - buf[1] = (uint8_t)((timeout >> 8) & 0xFF); - buf[2] = (uint8_t)(timeout & 0xFF); - WriteCommand(SX126X_CMD_SET_RX, buf, 3); // 0x82 - - for(int retry=0;retry<10;retry++) { - if ((GetStatus() & 0x70) == 0x50) break; - delay(1); - } - if ((GetStatus() & 0x70) != 0x50) { - ESP_LOGE(TAG, "SetRx Illegal Status"); - LoRaError(ERR_INVALID_SETRX_STATE); - } -} - - -void SetRxEnable(void) -{ - if (debugPrint) { - ESP_LOGI(TAG, "SetRxEnable:SX126x_TXEN=%d SX126x_RXEN=%d", SX126x_TXEN, SX126x_RXEN); - } - if ((SX126x_TXEN != -1) && (SX126x_RXEN != -1)) { - gpio_set_level(SX126x_RXEN, HIGH); - gpio_set_level(SX126x_TXEN, LOW); - } -} - - -void SetTx(uint32_t timeoutInMs) -{ - if (debugPrint) { - ESP_LOGI(TAG, "----- SetTx timeoutInMs=%"PRIu32, timeoutInMs); - } - SetStandby(SX126X_STANDBY_RC); - SetTxEnable(); - uint8_t buf[3]; - uint32_t tout = timeoutInMs; - if (timeoutInMs != 0) { - uint32_t timeoutInUs = timeoutInMs * 1000; - tout = (uint32_t)(timeoutInUs / 0.015625); - } - if (debugPrint) { - ESP_LOGI(TAG, "SetTx timeoutInMs=%"PRIu32" tout=%"PRIu32, timeoutInMs, tout); - } - buf[0] = (uint8_t)((tout >> 16) & 0xFF); - buf[1] = (uint8_t)((tout >> 8) & 0xFF); - buf[2] = (uint8_t )(tout & 0xFF); - WriteCommand(SX126X_CMD_SET_TX, buf, 3); // 0x83 - - for(int retry=0;retry<10;retry++) { - if ((GetStatus() & 0x70) == 0x60) break; - vTaskDelay(1); - } - if ((GetStatus() & 0x70) != 0x60) { - ESP_LOGE(TAG, "SetTx Illegal Status"); - LoRaError(ERR_INVALID_SETTX_STATE); - } -} - - -void SetTxEnable(void) -{ - if (debugPrint) { - ESP_LOGI(TAG, "SetTxEnable:SX126x_TXEN=%d SX126x_RXEN=%d", SX126x_TXEN, SX126x_RXEN); - } - if ((SX126x_TXEN != -1) && (SX126x_RXEN != -1)){ - gpio_set_level(SX126x_RXEN, LOW); - gpio_set_level(SX126x_TXEN, HIGH); - } -} - - -int GetPacketLost() -{ - return txLost; -} - - -uint8_t GetRssiInst() -{ - uint8_t buf[2]; - ReadCommand( SX126X_CMD_GET_RSSI_INST, buf, 2 ); // 0x15 - return buf[1]; -} - - -void GetRxBufferStatus(uint8_t *payloadLength, uint8_t *rxStartBufferPointer) -{ - uint8_t buf[3]; - ReadCommand( SX126X_CMD_GET_RX_BUFFER_STATUS, buf, 3 ); // 0x13 - *payloadLength = buf[1]; - *rxStartBufferPointer = buf[2]; -} - - -void WaitForIdleBegin(unsigned long timeout, char *text) { - // ensure BUSY is low (state meachine ready) - bool stop = false; - for (int retry=0;retry<10;retry++) { - if (retry == 9) stop = true; - bool ret = WaitForIdle(BUSY_WAIT, text, stop); - if (ret == true) break; - ESP_LOGW(TAG, "WaitForIdle fail retry=%d", retry); - vTaskDelay(1); - } -} - - -bool WaitForIdle(unsigned long timeout, char *text, bool stop) -{ - bool ret = true; - TickType_t start = xTaskGetTickCount(); - delayMicroseconds(1); - while(xTaskGetTickCount() - start < (timeout/portTICK_PERIOD_MS)) { - if (gpio_get_level(SX126x_BUSY) == 0) break; - delayMicroseconds(1); - } - if (gpio_get_level(SX126x_BUSY)) { - if (stop) { - ESP_LOGE(TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%"PRIu32, text, timeout, start); - LoRaError(ERR_IDLE_TIMEOUT); - } else { - ESP_LOGW(TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%"PRIu32, text, timeout, start); - ret = false; - } - } - return ret; -} - - -uint8_t ReadBuffer(uint8_t *rxData, int16_t rxDataLen) -{ - uint8_t offset = 0; - uint8_t payloadLength = 0; - GetRxBufferStatus(&payloadLength, &offset); - if( payloadLength > rxDataLen ) - { - ESP_LOGW(TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen); - return 0; - } - - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "start ReadBuffer", true); - - // start transfer - uint8_t *buf; - buf = malloc(payloadLength+3); - if (buf != NULL) { - buf[0] = SX126X_CMD_READ_BUFFER; // 0x1E - buf[1] = offset; // offset in rx fifo - buf[2] = SX126X_CMD_NOP; - memset(&buf[3], SX126X_CMD_NOP, payloadLength); - spi_read_byte(buf, buf, payloadLength+3); - memcpy(rxData, &buf[3], payloadLength); - free(buf); - } else { - ESP_LOGE(TAG, "ReadBuffer malloc fail"); - payloadLength = 0; - } - - // wait for BUSY to go low - WaitForIdle(BUSY_WAIT, "end ReadBuffer", false); - - return payloadLength; -} - - -void WriteBuffer(uint8_t *txData, int16_t txDataLen) -{ - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "start WriteBuffer", true); - - // start transfer - uint8_t *buf; - buf = malloc(txDataLen+2); - if (buf != NULL) { - buf[0] = SX126X_CMD_WRITE_BUFFER; // 0x0E - buf[1] = 0; // offset in tx fifo - memcpy(&buf[2], txData, txDataLen); - spi_write_byte(buf, txDataLen+2); - free(buf); - } else { - ESP_LOGE(TAG, "WriteBuffer malloc fail"); - } - - // wait for BUSY to go low - WaitForIdle(BUSY_WAIT, "end WriteBuffer", false); -} - - -void WriteRegister(uint16_t reg, uint8_t* data, uint8_t numBytes) { - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "start WriteRegister", true); - - if(debugPrint) { - ESP_LOGI(TAG, "WriteRegister: REG=0x%02x", reg); - for(uint8_t n = 0; n < numBytes; n++) { - ESP_LOGI(TAG, "DataOut:%02x ", data[n]); - } - } - - // start transfer - uint8_t buf[16]; - buf[0] = SX126X_CMD_WRITE_REGISTER; - buf[1] = (reg & 0xFF00) >> 8; - buf[2] = reg & 0xff; - memcpy(&buf[3], data, numBytes); - spi_write_byte(buf, 3 + numBytes); - - // wait for BUSY to go low - WaitForIdle(BUSY_WAIT, "end WriteRegister", false); -} - - -void ReadRegister(uint16_t reg, uint8_t* data, uint8_t numBytes) { - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "start ReadRegister", true); - - if(debugPrint) { - ESP_LOGI(TAG, "ReadRegister: REG=0x%02x", reg); - } - - // start transfer - uint8_t buf[16]; - memset(buf, SX126X_CMD_NOP, sizeof(buf)); - buf[0] = SX126X_CMD_READ_REGISTER; - buf[1] = (reg & 0xFF00) >> 8; - buf[2] = reg & 0xff; - spi_read_byte(buf, buf, 4 + numBytes); - memcpy(data, &buf[4], numBytes); - if(debugPrint) { - for(uint8_t n = 0; n < numBytes; n++) { - ESP_LOGI(TAG, "DataIn:%02x ", data[n]); - } - } - - // wait for BUSY to go low - WaitForIdle(BUSY_WAIT, "end ReadRegister", false); -} - -// WriteCommand with retry -void WriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes) { - uint8_t status; - for (int retry=1; retry<10; retry++) { - status = WriteCommand2(cmd, data, numBytes); - ESP_LOGD(TAG, "status=%02x", status); - if (status == 0) break; - ESP_LOGW(TAG, "WriteCommand2 status=%02x retry=%d", status, retry); - } - if (status != 0) { - ESP_LOGE(TAG, "SPI Transaction error:0x%02x", status); - LoRaError(ERR_SPI_TRANSACTION); - } -} - -uint8_t WriteCommand2(uint8_t cmd, uint8_t* data, uint8_t numBytes) { - // ensure BUSY is low (state meachine ready) - WaitForIdle(BUSY_WAIT, "start WriteCommand2", true); - - if(debugPrint) { - ESP_LOGI(TAG, "WriteCommand: CMD=0x%02x", cmd); - } - - // start transfer - uint8_t buf[16]; - buf[0] = cmd; - memcpy(&buf[1], data, numBytes); - spi_read_byte(buf, buf, numBytes + 1); - - uint8_t status = 0; - uint8_t cmd_status = buf[1] & 0xe; - - switch(cmd_status){ - case SX126X_STATUS_CMD_TIMEOUT: - case SX126X_STATUS_CMD_INVALID: - case SX126X_STATUS_CMD_FAILED: - status = cmd_status; - break; - - case 0: - case 7: - status = SX126X_STATUS_SPI_FAILED; - break; - // default: break; // success - } - - // wait for BUSY to go low - WaitForIdle(BUSY_WAIT, "end WriteCommand2", false); - return status; -} - - -void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes) { - // ensure BUSY is low (state meachine ready) - WaitForIdleBegin(BUSY_WAIT, "start ReadCommand"); - - if(debugPrint) { - ESP_LOGI(TAG, "ReadCommand: CMD=0x%02x", cmd); - } - - // start transfer - uint8_t buf[16]; - memset(buf, SX126X_CMD_NOP, sizeof(buf)); - buf[0] = cmd; - spi_read_byte(buf, buf, 1 + numBytes); - if (data != NULL && numBytes) - memcpy(data, &buf[1], numBytes); - - // wait for BUSY to go low - vTaskDelay(1); - WaitForIdle(BUSY_WAIT, "end ReadCommand", false); -} diff --git a/components/ra01s/ra01s.h b/components/ra01s/ra01s.h deleted file mode 100755 index a48e0b0..0000000 --- a/components/ra01s/ra01s.h +++ /dev/null @@ -1,436 +0,0 @@ -#ifndef _RA01S_H -#define _RA01S_H - -#include "driver/spi_master.h" - -//return values -#define ERR_NONE 0 -#define ERR_PACKET_TOO_LONG 1 -#define ERR_UNKNOWN 2 -#define ERR_TX_TIMEOUT 3 -#define ERR_RX_TIMEOUT 4 -#define ERR_CRC_MISMATCH 5 -#define ERR_WRONG_MODEM 6 -#define ERR_INVALID_BANDWIDTH 7 -#define ERR_INVALID_SPREADING_FACTOR 8 -#define ERR_INVALID_CODING_RATE 9 -#define ERR_INVALID_FREQUENCY_DEVIATION 10 -#define ERR_INVALID_BIT_RATE 11 -#define ERR_INVALID_RX_BANDWIDTH 12 -#define ERR_INVALID_DATA_SHAPING 13 -#define ERR_INVALID_SYNC_WORD 14 -#define ERR_INVALID_OUTPUT_POWER 15 -#define ERR_INVALID_MODE 16 -#define ERR_INVALID_TRANCEIVER 17 -#define ERR_INVALID_SETRX_STATE 18 -#define ERR_INVALID_SETTX_STATE 19 -#define ERR_IDLE_TIMEOUT 20 -#define ERR_SPI_TRANSACTION 21 - -// SX126X physical layer properties -#define XTAL_FREQ ( double )32000000 -#define FREQ_DIV ( double )pow( 2.0, 25.0 ) -#define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV ) - -#define LOW 0 -#define HIGH 1 -#define BUSY_WAIT 5000 - -// SX126X Model -#define SX1261_TRANCEIVER 0x01 -#define SX1262_TRANCEIVER 0x02 -#define SX1268_TRANCEIVER 0x08 - -// SX126X SPI commands -// operational modes commands -#define SX126X_CMD_NOP 0x00 -#define SX126X_CMD_SET_SLEEP 0x84 -#define SX126X_CMD_SET_STANDBY 0x80 -#define SX126X_CMD_SET_FS 0xC1 -#define SX126X_CMD_SET_TX 0x83 -#define SX126X_CMD_SET_RX 0x82 -#define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F -#define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94 -#define SX126X_CMD_SET_CAD 0xC5 -#define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1 -#define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2 -#define SX126X_CMD_SET_REGULATOR_MODE 0x96 -#define SX126X_CMD_CALIBRATE 0x89 -#define SX126X_CMD_CALIBRATE_IMAGE 0x98 -#define SX126X_CMD_SET_PA_CONFIG 0x95 -#define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93 - -// register and buffer access commands -#define SX126X_CMD_WRITE_REGISTER 0x0D -#define SX126X_CMD_READ_REGISTER 0x1D -#define SX126X_CMD_WRITE_BUFFER 0x0E -#define SX126X_CMD_READ_BUFFER 0x1E - -// DIO and IRQ control -#define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08 -#define SX126X_CMD_GET_IRQ_STATUS 0x12 -#define SX126X_CMD_CLEAR_IRQ_STATUS 0x02 -#define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D -#define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97 - -// RF, modulation and packet commands -#define SX126X_CMD_SET_RF_FREQUENCY 0x86 -#define SX126X_CMD_SET_PACKET_TYPE 0x8A -#define SX126X_CMD_GET_PACKET_TYPE 0x11 -#define SX126X_CMD_SET_TX_PARAMS 0x8E -#define SX126X_CMD_SET_MODULATION_PARAMS 0x8B -#define SX126X_CMD_SET_PACKET_PARAMS 0x8C -#define SX126X_CMD_SET_CAD_PARAMS 0x88 -#define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F -#define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0 - -#define SX126X_PA_CONFIG_SX1261 0x01 -#define SX126X_PA_CONFIG_SX1262 0x00 - -// status commands -#define SX126X_CMD_GET_STATUS 0xC0 -#define SX126X_CMD_GET_RSSI_INST 0x15 -#define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13 -#define SX126X_CMD_GET_PACKET_STATUS 0x14 -#define SX126X_CMD_GET_DEVICE_ERRORS 0x17 -#define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07 -#define SX126X_CMD_GET_STATS 0x10 -#define SX126X_CMD_RESET_STATS 0x00 - - -// SX126X register map -#define SX126X_REG_HOPPING_ENABLE 0x0385 -#define SX126X_REG_PACKECT_LENGTH 0x0386 -#define SX126X_REG_NB_HOPPING_BLOCKS 0x0387 -#define SX126X_REG_NB_SYMBOLS0 0x0388 -#define SX126X_REG_FREQ0 0x038A -#define SX126X_REG_NB_SYMBOLS15 0x03E2 -#define SX126X_REG_FREQ15 0x03E4 -#define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580 -#define SX126X_REG_DIOX_INPUT_ENABLE 0x0583 -#define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584 -#define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585 -#define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8 -#define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9 -#define SX126X_REG_CRC_INITIAL_MSB 0x06BC -#define SX126X_REG_CRC_INITIAL_LSB 0x06BD -#define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE -#define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF -#define SX126X_REG_SYNC_WORD_0 0x06C0 -#define SX126X_REG_SYNC_WORD_1 0x06C1 -#define SX126X_REG_SYNC_WORD_2 0x06C2 -#define SX126X_REG_SYNC_WORD_3 0x06C3 -#define SX126X_REG_SYNC_WORD_4 0x06C4 -#define SX126X_REG_SYNC_WORD_5 0x06C5 -#define SX126X_REG_SYNC_WORD_6 0x06C6 -#define SX126X_REG_SYNC_WORD_7 0x06C7 -#define SX126X_REG_NODE_ADDRESS 0x06CD -#define SX126X_REG_BROADCAST_ADDRESS 0x06CE -#define SX126X_REG_IQ_POLARITY_SETUP 0x0736 -#define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740 -#define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741 -#define SX126X_REG_RANDOM_NUMBER_0 0x0819 -#define SX126X_REG_RANDOM_NUMBER_1 0x081A -#define SX126X_REG_RANDOM_NUMBER_2 0x081B -#define SX126X_REG_RANDOM_NUMBER_3 0x081C -#define SX126X_REG_TX_MODULETION 0x0889 -#define SX126X_REG_RX_GAIN 0x08AC -#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8 -#define SX126X_REG_OCP_CONFIGURATION 0x08E7 -#define SX126X_REG_RTC_CONTROL 0x0902 -#define SX126X_REG_XTA_TRIM 0x0911 -#define SX126X_REG_XTB_TRIM 0x0912 -#define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920 -#define SX126X_REG_EVENT_MASK 0x0944 - - -// SX126X SPI command variables -//SX126X_CMD_SET_SLEEP -#define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default) -#define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained -#define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled -#define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled - -//SX126X_CMD_SET_STANDBY -#define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator -#define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator - -//SX126X_CMD_SET_RX -#define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode) -#define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode) - -//SX126X_CMD_STOP_TIMER_ON_PREAMBLE -#define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default) -#define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection - -//SX126X_CMD_SET_REGULATOR_MODE -#define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default) -#define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC - -//SX126X_CMD_CALIBRATE -#define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled -#define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled -#define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled -#define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled -#define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled -#define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled -#define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled -#define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled -#define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled -#define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled -#define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled -#define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled -#define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled -#define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled - -//SX126X_CMD_CALIBRATE_IMAGE -#define SX126X_CAL_IMG_430_MHZ_1 0x6B -#define SX126X_CAL_IMG_430_MHZ_2 0x6F -#define SX126X_CAL_IMG_470_MHZ_1 0x75 -#define SX126X_CAL_IMG_470_MHZ_2 0x81 -#define SX126X_CAL_IMG_779_MHZ_1 0xC1 -#define SX126X_CAL_IMG_779_MHZ_2 0xC5 -#define SX126X_CAL_IMG_863_MHZ_1 0xD7 -#define SX126X_CAL_IMG_863_MHZ_2 0xDB -#define SX126X_CAL_IMG_902_MHZ_1 0xE1 -#define SX126X_CAL_IMG_902_MHZ_2 0xE9 - -//SX126X_CMD_SET_PA_CONFIG -#define SX126X_PA_CONFIG_HP_MAX 0x07 -#define SX126X_PA_CONFIG_SX1268 0x01 -#define SX126X_PA_CONFIG_PA_LUT 0x01 - -//SX126X_CMD_SET_RX_TX_FALLBACK_MODE -#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode -#define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator -#define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default) - -//SX126X_CMD_SET_DIO_IRQ_PARAMS -#define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout -#define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected -#define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished -#define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received -#define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error -#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received -#define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected -#define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected -#define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received -#define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed -#define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts -#define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts - -//SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL -#define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ -#define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control - -//SX126X_CMD_SET_DIO3_AS_TCXO_CTRL -#define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V -#define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V -#define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V -#define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V -#define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V -#define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V -#define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V -#define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V - -//Radio complete Wake-up Time with TCXO stabilisation time -#define RADIO_TCXO_SETUP_TIME 5000 // [us] - -//SX126X_CMD_SET_PACKET_TYPE -#define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK -#define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa - -//SX126X_CMD_SET_TX_PARAMS -#define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us -#define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us -#define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us -#define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us -#define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us -#define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us -#define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us -#define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us - -//SX126X_CMD_SET_MODULATION_PARAMS -#define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none -#define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3 -#define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5 -#define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7 -#define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1 -#define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz -#define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz -#define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz -#define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz -#define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz -#define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz -#define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz -#define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz -#define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz -#define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz -#define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz -#define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz -#define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz -#define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz -#define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz -#define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz -#define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz -#define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz -#define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz -#define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz -#define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz -#define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz -#define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz -#define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz -#define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz -#define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz -#define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz -#define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz -#define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz -#define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz -#define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz -#define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5 -#define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6 -#define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7 -#define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8 -#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled -#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled - -//SX126X_CMD_SET_PACKET_PARAMS -#define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled -#define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits -#define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits -#define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits -#define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits -#define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled -#define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only -#define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast -#define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides) -#define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet) -#define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled -#define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte -#define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte -#define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted -#define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted -#define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled -#define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled -#define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit -#define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit -#define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled -#define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled -#define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard -#define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted - -//SX126X_CMD_SET_CAD_PARAMS -#define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1 -#define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2 -#define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4 -#define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8 -#define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16 -#define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode -#define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected - -//SX126X_CMD_GET_STATUS -#define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC -#define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC -#define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS -#define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX -#define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX -#define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved -#define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out -#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command -#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute -#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done -#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed - -//SX126X_CMD_GET_PACKET_STATUS -#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error -#define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error -#define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error -#define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error -#define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error -#define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error -#define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received -#define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent - -//SX126X_CMD_GET_DEVICE_ERRORS -#define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed -#define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock -#define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start -#define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed -#define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed -#define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed -#define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed -#define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed - - -// SX126X SPI register variables -//SX126X_REG_LORA_SYNC_WORD_MSB + LSB -#define SX126X_SYNC_WORD_PUBLIC 0x3444 -#define SX126X_SYNC_WORD_PRIVATE 0x1424 - -#define SX126x_TXMODE_ASYNC 0x01 -#define SX126x_TXMODE_SYNC 0x02 -#define SX126x_TXMODE_BACK2RX 0x04 - -// Public function -void LoRaInit(void); -int16_t LoRaBegin(uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, bool useRegulatorLDO); -void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, bool crcOn, bool invertIrq); -uint8_t LoRaReceive(uint8_t *pData, int16_t len); -bool LoRaSend(uint8_t *pData, int16_t len, uint8_t mode); -void LoRaDebugPrint(bool enable); - -// Private function -void spi_write_byte(uint8_t* Dataout, size_t DataLength ); -void spi_read_byte(uint8_t* Datain, uint8_t* Dataout, size_t DataLength ); -uint8_t spi_transfer(uint8_t address); - -bool ReceiveMode(void); -void GetPacketStatus(int8_t *rssiPacket, int8_t *snrPacket); -void SetTxPower(int8_t txPowerInDbm); - -void FixInvertedIQ(uint8_t iqConfig); -void SetDio3AsTcxoCtrl(float voltage, uint32_t delay); -void SetDio2AsRfSwitchCtrl(uint8_t enable); -void Reset(void); -void SetStandby(uint8_t mode); -void SetRfFrequency(uint32_t frequency); -void Calibrate(uint8_t calibParam); -void CalibrateImage(uint32_t frequency); -void SetRegulatorMode(uint8_t mode); -void SetBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); -void SetPowerConfig(int8_t power, uint8_t rampTime); -void SetOvercurrentProtection(float currentLimit); -void SetSyncWord(int16_t sync); -void SetPaConfig(uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut); -void SetDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask); -void SetStopRxTimerOnPreambleDetect(bool enable); -void SetLoRaSymbNumTimeout(uint8_t SymbNum); -void SetPacketType(uint8_t packetType); -void SetModulationParams(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize); -void SetCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout); -void SetCad(); -uint8_t GetStatus(void); -uint16_t GetIrqStatus(void); -void ClearIrqStatus(uint16_t irq); -void SetTxEnable(void); -void SetRxEnable(void); -void SetRx(uint32_t timeout); -void SetTx(uint32_t timeoutInMs); -int GetPacketLost(); -uint8_t GetRssiInst(); -void GetRxBufferStatus(uint8_t *payloadLength, uint8_t *rxStartBufferPointer); -void Wakeup(void); -void WaitForIdleBegin(unsigned long timeout, char *text); -bool WaitForIdle(unsigned long timeout, char *text, bool stop); -uint8_t ReadBuffer(uint8_t *rxData, int16_t rxDataLen); -void WriteBuffer(uint8_t *txData, int16_t txDataLen); -void WriteRegister(uint16_t reg, uint8_t* data, uint8_t numBytes); -void ReadRegister(uint16_t reg, uint8_t* data, uint8_t numBytes); -void WriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes); -uint8_t WriteCommand2(uint8_t cmd, uint8_t* data, uint8_t numBytes); -void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes); -void SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy); -void LoRaError(int error); - - -#endif diff --git a/dependencies.lock b/dependencies.lock index 20bbb23..2a59adb 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -2,7 +2,7 @@ dependencies: idf: source: type: idf - version: 5.4.1 + version: 5.5.0 k0i05/esp_bme680: component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8 dependencies: diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 49aef2a..d8774d5 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -13,8 +13,16 @@ idf_component_register(SRCS "hw/mcp23018.h" "hw/mpu9250.c" "hw/mpu9250.h" +"hw/gps.c" +"hw/gps.h" +"hw/mcp3550.c" +"hw/mcp3550.h" +"hw/sx1262.c" +"hw/sx1262.h" "components/sensors.c" "components/sensors.h" +"components/radio.c" +"components/radio.h" "main.c" INCLUDE_DIRS ".") diff --git a/main/components/packets.h b/main/components/packets.h new file mode 100644 index 0000000..e69de29 diff --git a/main/components/radio.c b/main/components/radio.c new file mode 100644 index 0000000..303907b --- /dev/null +++ b/main/components/radio.c @@ -0,0 +1,207 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "../hw/sx1262.h" +#include "radio.h" + +const char *msg = "Testing 123 test why is this not on air"; + +void lora_comms_task(void *pvParameters) +{ + sx1262_init(); + sx1262_resetStats(); + ESP_LOGI(TAG_RADIO, "Setting standby RC"); + sx1262_setStandby(SX1262_STANDBY_RC); + + ESP_LOGI(TAG_RADIO, "Getting version"); + unsigned char versDat[16]; + sx1262_readRegister(0x0320, versDat, 16); + ESP_LOGI(TAG_RADIO, "Version: %s", versDat); + + sx1262_get_status(); + + // Read status + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting TCXO"); + sx1262_setDIO3AsTCXOCtrl(SX1262_TCXO_VOLTAGE22dV, 320); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting Buffer base address"); + sx1262_setBufferBaseAddress(0, 0); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting packet Type"); + sx1262_setPacketType(SX1262_PACKET_TYPE_LORA); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting RXTX fallback mode"); + sx1262_setRxTXFallbackMode(SX1262_FALLBACK_RC); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting CAD params"); + sx1262_setCadParams(0x03, 0x16, 0x0A, 0, 0); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Clearing IRQ status"); + sx1262_clearIrqStatus(0x43FF); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting Image rejection"); + sx1262_calibrateImage(0xD7, 0xDB); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Calibrating Image rejection"); + sx1262_calibrate(SX1262_CALIBRATION_ALL); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting regulator"); + sx1262_setRegulatorMode(SX1262_REGULATOR_DC_DC_LDO); + sx1262_get_status(); + + uint8_t modType; + modType = sx1262_getPacketType(); + sx1262_get_status(); + ESP_LOGI(TAG_RADIO, "ModType %d", modType); + + sx1262_LoRaModulationParams_t loraModParams; + + loraModParams.bandwidth = SX1262_LORA_BW_125; + loraModParams.codingRate = SX1262_LORA_CR_4_5; + loraModParams.lowDataRateOpt = 1; + loraModParams.spreadingFactor = SX1262_LORA_SF7; + + ESP_LOGI(TAG_RADIO, "Setting modulation params"); + sx1262_setLoRaModulationParams(&loraModParams); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting Sync word"); + uint8_t syncWord[2] = {0x14, 0x24}; + + sx1262_writeRegister(SX1262_LORA_SYNC_WORD_MSB, syncWord, 2); + sx1262_get_status(); + + uint8_t ocpBuf[1] = {SX126X_OCP_LEVEL_SX1262}; + + ESP_LOGI(TAG_RADIO, "Setting overcurrent protection"); + sx1262_writeRegister(SX126X_OCP_CONFIGURATION, ocpBuf, 1); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting RF Switch out"); + sx1262_setDIO2AsRfSwitchCtrl(1); + + sx1262_get_status(); + + sx1262_LoRaPacketParams_t loraPacketParams; + loraPacketParams.preambleLength = 10; + loraPacketParams.crcType = SX1262_CRC_ON; + loraPacketParams.headerType = SX1262_HEADER_TYPE_VARIABLE; + loraPacketParams.invertIQ = SX1262_STANDARD_IQ; + loraPacketParams.payloadLength = sizeof(msg); + + ESP_LOGI(TAG_RADIO, "Setting packet params"); + sx1262_setLoRaPacketParams(&loraPacketParams); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting frequency"); + sx1262_setFrequency(869525000); + + uint8_t clampConfig[1] = {0xDE}; + + ESP_LOGI(TAG_RADIO, "Setting TX clamp"); + sx1262_writeRegister(SX126X_TX_CLAMP_CONFIG, clampConfig, 1); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting TX power"); + sx1262_configure_tx_power(0x04, 0x07, 0x01, LORA_TX_POWER, SX1262_Ramp_200U); + + sx1262_get_status(); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting standby XOSC"); + sx1262_setStandby(SX1262_STANDBY_XOSC); + + sx1262_get_status(); + + sx1262_setDioIrqParams(SX1262_IRQ_ALL, SX1262_IRQ_TXDone, 0, 0); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Setting buffer base address"); + sx1262_setBufferBaseAddress(0, 0); + + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Writing message"); + sx1262_writeBuffer(0, (uint8_t *)msg, sizeof(msg)); + + ESP_LOGI(TAG_RADIO, "Clearing IRQs"); + sx1262_clearIrqStatus(SX1262_IRQ_ALL); + + // sx1262_setTxContinuousWave(); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Getting modulation type..."); + modType = sx1262_getPacketType(); + ESP_LOGI(TAG_RADIO, "ModType %d", modType); + sx1262_get_status(); + + // ESP_LOGI(TAG_RADIO, "Enabling CW..."); + // sx1262_setTxContinuousWave(); + // sx1262_get_status(); + + uint8_t txModulation[1] = {0x04}; + + ESP_LOGI(TAG_RADIO, "Setting modulation thing"); + sx1262_writeRegister(SX126X_TX_MODULATION, txModulation, 1); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Clearing IRQs"); + sx1262_clearIrqStatus(SX1262_IRQ_ALL); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Enabling TX..."); + sx1262_setMode(SX1262_TRANSMIT_MODE, 0); + sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Waiting for TX finish"); + while (1) + { + if (gpio_get_level(LORA_DIO1)) + { + ESP_LOGI(TAG_RADIO, "Got IRQin"); + uint16_t irqS = sx1262_getIrqStatus(); + if (irqS & SX1262_IRQ_TXDone) + { + break; + } + } + vTaskDelay(pdMS_TO_TICKS(10)); + } + + // vTaskDelay(pdMS_TO_TICKS(2000)); + // ESP_LOGI(TAG_RADIO, "Returning back to sleep"); + // sx1262_setStandby(SX1262_STANDBY_XOSC); + + // sx1262_get_status(); + + ESP_LOGI(TAG_RADIO, "Clearing IRQs"); + sx1262_clearIrqStatus(SX1262_IRQ_TXDone); + + sx1262_get_status(); + while (1) + { + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + // Set frequency to 868 MHz + + // Set TX power to 22 dBm + + // sx1262_setTxContinuousWave(); +} \ No newline at end of file diff --git a/main/components/radio.h b/main/components/radio.h new file mode 100644 index 0000000..19684b3 --- /dev/null +++ b/main/components/radio.h @@ -0,0 +1,14 @@ +#ifndef RADIO_COMPONENT +#define RADIO_COMPONENT + +#define LORA_POWER_LOW 2 +#define LORA_POWER_HIGH 20 +#define LORA_POWER_MAX_MAYBE_UNSAFE 22 + +#define LORA_TX_POWER LORA_POWER_LOW + +#define TAG_RADIO "RADIO" + +void lora_comms_task(void *pvParameters); + +#endif \ No newline at end of file diff --git a/main/components/sensors.c b/main/components/sensors.c index 843ca34..a83be22 100644 --- a/main/components/sensors.c +++ b/main/components/sensors.c @@ -20,16 +20,20 @@ void i2c_sensors_task(void *pvParameters) bme680b_init(); mpu9250_init(); - mcp23018_init(); ina260_init(); ccs811_init(); + mcp3550_spi_init(); configure_led(); int16_t accel[3], gyro[3], temp; float accel_f[3], gyro_f[3], temp_f; + uint16_t eCO2; uint16_t tvoc; + uint8_t currentCCS; + uint16_t rawData; + uint16_t volts; uint16_t current; uint16_t power; @@ -51,19 +55,23 @@ void i2c_sensors_task(void *pvParameters) else { data.barometric_pressure = data.barometric_pressure / 100; - // ESP_LOGI(TAG, "dewpoint temperature:%.2f °C", data.dewpoint_temperature); + ESP_LOGI(TAG_BME, "dewpoint temperature:%.2f °C", data.dewpoint_temperature); ESP_LOGI(TAG_BME, "air temperature: %.2f °C", data.air_temperature); ESP_LOGI(TAG_BME, "relative humidity: %.2f %%", data.relative_humidity); ESP_LOGI(TAG_BME, "barometric pressure: %.2f hPa", data.barometric_pressure); - // ESP_LOGI(TAG, "gas resistance: %.2f kOhms", data.gas_resistance / 1000); - // ESP_LOGI(TAG, "iaq score: %u (%s)", data.iaq_score, bme680_air_quality_to_string(data.iaq_score)); + ccs811_set_env_data(data.air_temperature, data.relative_humidity); + ESP_LOGI(TAG_BME, "gas resistance: %.2f kOhms", data.gas_resistance / 1000); + ESP_LOGI(TAG_BME, "iaq score: %u (%s)", data.iaq_score, bme680_air_quality_to_string(data.iaq_score)); } - } else { + } + else + { bme680b_init(); } - ccs811_get_data(&eCO2, &tvoc); + ccs811_get_data(&eCO2, &tvoc, ¤tCCS, &rawData); ESP_LOGI(TAG_CCS, "eCO₂: %d ppm, TVOC: %d ppb", eCO2, tvoc); + ESP_LOGI(TAG_CCS, "Current: %d μA, Raw voltage: %d V", currentCCS, rawData); if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp) == ESP_OK) { @@ -81,6 +89,15 @@ void i2c_sensors_task(void *pvParameters) ina260_readParams(&volts, ¤t, &power); ina260_printParams(volts, current, power); + float VREFVoltage = volts * 1.25 / 1000; //Mame vobec nieco na VREFE? Na scheme su len medzi sebou prepojene + + mics_adc_data_t ADCData = mcp3550_read_all(5.0); // vref = 5.0V + log_mics_adc_values(&ADCData); + + ADCData = mcp3550_read_all(VREFVoltage); + + log_mics_adc_values(&ADCData); + gpio_set_level(BLINK_GPIO, s_led_state); /* Toggle the LED state */ s_led_state = !s_led_state; diff --git a/main/components/sensors.h b/main/components/sensors.h index bd5c647..91a0f3f 100644 --- a/main/components/sensors.h +++ b/main/components/sensors.h @@ -7,6 +7,8 @@ #include #include "esp_mac.h" +#include "../hw/mcp3550.h" + #include "../hw/bme680b.h" #include "../hw/ccs811.h" #include "../hw/i2cbrn.h" diff --git a/main/hw/buscfg.h b/main/hw/buscfg.h new file mode 100644 index 0000000..42a0721 --- /dev/null +++ b/main/hw/buscfg.h @@ -0,0 +1,70 @@ +#ifndef BUSCFG_FILE +#define BUSCFG_FILE + +#include "soc/gpio_num.h" + +#define ESP_USB_DP GPIO_NUM_20 +#define ESP_USB_DM GPIO_NUM_19 +#define ESP_RXD0 GPIO_NUM_44 +#define ESP_TXD0 GPIO_NUM_43 + +#define ESP_CONNECTOR_P1 MCP3550_MISO_GPIO +#define ESP_CONNECTOR_P2 MCP3550_MOSI_GPIO +#define ESP_CONNECTOR_P3 MCP3550_SCK_GPIO +#define ESP_CONNECTOR_P4 GPIO_NUM_39 +#define ESP_CONNECTOR_P5 GPIO_NUM_38 +#define ESP_CONNECTOR_P6 HSPI_UNKNOWN_CS +#define ESP_CONNECTOR_P9 HSPI_MISO_GPIO +#define ESP_CONNECTOR_P10 MCP3550_MOSI_GPIO +#define ESP_CONNECTOR_P11 MCP3550_SCK_GPIO +#define ESP_CONNECTOR_P12 HSPI_SD_CS +#define ESP_CONNECTOR_P13 HSPI_LORA_CS +#define ESP_CONNECTOR_P17 HWI2C_SDA +#define ESP_CONNECTOR_P18 HWI2C_SCL +#define ESP_CONNECTOR_P19 I2C2_SDA +#define ESP_CONNECTOR_P20 I2C2_SCL +#define ESP_CONNECTOR_P25 LORA_DIO1 +#define ESP_CONNECTOR_P26 LORA_BUSY +#define ESP_CONNECTOR_P27 LORA_RXEN_MANUAL +#define ESP_CONNECTOR_P28 GPIO_NUM_6 +#define ESP_CONNECTOR_P29 GPIO_NUM_5 +#define ESP_CONNECTOR_P30 GPIO_NUM_4 +#define ESP_CONNECTOR_P47 GPS_RXD +#define ESP_CONNECTOR_P48 GPS_TXD +#define ESP_CONNECTOR_P51 ESP_RXD0 +#define ESP_CONNECTOR_P52 ESP_TXD0 +#define ESP_CONNECTOR_P57 ESP_USB_DP +#define ESP_CONNECTOR_P58 ESP_USB_DM + + +#define HSPI_UNKNOWN_CS GPIO_NUM_42 +#define LORA_RXEN_MANUAL GPIO_NUM_7 + +#define HSPI_MISO_GPIO GPIO_NUM_13 +#define HSPI_MOSI_GPIO GPIO_NUM_11 +//#define HSPI_MISO_GPIO GPIO_NUM_11 +//#define HSPI_MOSI_GPIO GPIO_NUM_13 + +#define HSPI_SCK_GPIO GPIO_NUM_12 +#define HSPI_LORA_CS GPIO_NUM_48 +#define LORA_DIO1 GPIO_NUM_16 +#define LORA_BUSY GPIO_NUM_15 +#define HSPI_SD_CS GPIO_NUM_10 + +#define MCP3550_MOSI_GPIO GPIO_NUM_35 +#define MCP3550_SCK_GPIO GPIO_NUM_36 +#define MCP3550_MISO_GPIO GPIO_NUM_37 + +#define GPS_TXD GPIO_NUM_17 +#define GPS_RXD GPIO_NUM_18 +#define GPS_RTS UART_PIN_NO_CHANGE +#define GPS_CTS UART_PIN_NO_CHANGE + +#define GPS_UART_NUM UART_NUM_2 + +#define HWI2C_SDA GPIO_NUM_8 +#define HWI2C_SCL GPIO_NUM_9 +#define I2C2_SDA GPIO_NUM_40 +#define I2C2_SCL GPIO_NUM_41 + +#endif \ No newline at end of file diff --git a/main/hw/ccs811.c b/main/hw/ccs811.c index 54948e6..3739679 100644 --- a/main/hw/ccs811.c +++ b/main/hw/ccs811.c @@ -10,6 +10,22 @@ i2c_device_config_t CCS811_DEV_CFG = { i2c_master_dev_handle_t CCS811_DEV_HANDLE; +void ccs811_getStatus() +{ + uint8_t errorID; + uint8_t status; + uint8_t hardwareVersion; + uint16_t version; + uint16_t bootVersion; + + i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_STATUS, &status); + i2c_read_register_16(CCS811_DEV_HANDLE, CCS811_REG_FW_APP_VERSION, &version); + i2c_read_register_16(CCS811_DEV_HANDLE, CCS811_REG_FW_BOOT_VERSION, &bootVersion); + i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_HW_VERSION, &hardwareVersion); + i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_ERROR_ID, &errorID); + ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d, boot version: %d, hardware version: %d, error ID: %d", status, version, bootVersion, hardwareVersion, errorID); +} + void ccs811_init() { ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE)); @@ -17,30 +33,47 @@ void ccs811_init() mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1); vTaskDelay(10 / portTICK_PERIOD_MS); uint8_t reset_seq[4] = {0x11, 0xE5, 0x72, 0x8A}; - i2c_write_register(CCS811_DEV_HANDLE, 0xFF, reset_seq, sizeof(reset_seq)); //Reset + i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_SW_RESET, reset_seq, sizeof(reset_seq)); // Reset vTaskDelay(10 / portTICK_PERIOD_MS); - uint8_t status; - uint16_t version; - i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status); - i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version); - ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version); - i2c_write_register(CCS811_DEV_HANDLE, 0xF4, NULL, 0); //start - vTaskDelay(10 / portTICK_PERIOD_MS); - i2c_write_register_8(CCS811_DEV_HANDLE, 0x10, 0x0001); // MODE 1 interrupts vypnuté - i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status); - i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version); - ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version); -} -esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc) + ccs811_getStatus(); + i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_APP_START, NULL, 0); // start + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_register_8(CCS811_DEV_HANDLE, CCS811_REG_MEAS_MODE, 0x40); // MODE 1 interrupts vypnuté + ccs811_getStatus(); +} +esp_err_t ccs811_get_data(uint16_t *eCO2, uint16_t *tvoc, uint8_t *current, uint16_t *rawData) { - uint8_t ccsResult[8]; - esp_err_t ret = i2c_read_register(CCS811_DEV_HANDLE, 0x05, ccsResult, 8); + uint8_t algResultData[8]; + esp_err_t ret = i2c_read_register(CCS811_DEV_HANDLE, CCS811_REG_ALG_RESULT_DATA, algResultData, 8); + if (ret == ESP_OK) { - *eCO2 = (((uint16_t)(ccsResult[0] & 0xFF)) << 8) | (ccsResult[1] & 0xFF); - *tvoc = (((uint16_t)(ccsResult[2] & 0xFF)) << 8) | (ccsResult[3] & 0xFF); - ESP_LOGI(TAG_CCS, "CCS Status: %d, Error %d", ccsResult[4], ccsResult[5]); + *eCO2 = ((uint16_t)algResultData[0] << 8) | algResultData[1]; + *tvoc = ((uint16_t)algResultData[2] << 8) | algResultData[3]; + *current = algResultData[6] >> 2; + *rawData = ((uint16_t)(algResultData[6] & 0x03) << 8) | algResultData[7]; + + ESP_LOGI(TAG_CCS, "CCS Status: %d, Error: %d", algResultData[4], algResultData[5]); + return ESP_OK; } + return ret; -} \ No newline at end of file +} + +esp_err_t ccs811_set_env_data(float temperature, float humidity) +{ + uint8_t envData[4]; + + // Convert humidity: %RH × 512 (rounding) + uint16_t hum_conv = (uint16_t)(humidity * 512.0f + 0.5f); + envData[0] = (hum_conv >> 8) & 0xFF; + envData[1] = hum_conv & 0xFF; + + // Convert temperature: (°C + 25) × 512 + uint16_t temp_conv = (uint16_t)((temperature + 25.0f) * 512.0f + 0.5f); + envData[2] = (temp_conv >> 8) & 0xFF; + envData[3] = temp_conv & 0xFF; + + return i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_ENV_DATA, envData, 4); +} diff --git a/main/hw/ccs811.h b/main/hw/ccs811.h index c925f72..413ad81 100644 --- a/main/hw/ccs811.h +++ b/main/hw/ccs811.h @@ -5,11 +5,39 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #define TAG_CCS "CCS811" + +// CCS811 Registers +#define CCS811_REG_STATUS 0x00 +#define CCS811_REG_MEAS_MODE 0x01 +#define CCS811_REG_ALG_RESULT_DATA 0x02 +#define CCS811_REG_RAW_DATA 0x03 +#define CCS811_REG_ENV_DATA 0x05 +#define CCS811_REG_THRESHOLDS 0x10 +#define CCS811_REG_BASELINE 0x11 +#define CCS811_REG_HW_ID 0x20 +#define CCS811_REG_HW_VERSION 0x21 +#define CCS811_REG_FW_BOOT_VERSION 0x23 +#define CCS811_REG_FW_APP_VERSION 0x24 +#define CCS811_REG_INTERNAL_STATE 0xA0 +#define CCS811_REG_ERROR_ID 0xE0 +#define CCS811_REG_APP_ERASE 0xF1 +#define CCS811_REG_APP_DATA 0xF2 +#define CCS811_REG_APP_VERIFY 0xF3 +#define CCS811_REG_APP_START 0xF4 +#define CCS811_REG_SW_RESET 0xFF + +// Measurement Modes +#define CCS811_MODE_IDLE 0x00 +#define CCS811_MODE_CONSTANT_1S 0x10 +#define CCS811_MODE_CONSTANT_10S 0x20 +#define CCS811_MODE_CONSTANT_60S 0x30 +#define CCS811_MODE_WAKEUP 0x40 + extern i2c_device_config_t CCS811_DEV_CFG; extern i2c_master_dev_handle_t CCS811_DEV_HANDLE; void ccs811_init(); -esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc); - +esp_err_t ccs811_get_data(uint16_t *eCO2, uint16_t *tvoc, uint8_t *current, uint16_t *rawData); +esp_err_t ccs811_set_env_data(float temperature, float humidity); #endif \ No newline at end of file diff --git a/main/hw/gps.c b/main/hw/gps.c new file mode 100644 index 0000000..0b363fa --- /dev/null +++ b/main/hw/gps.c @@ -0,0 +1,136 @@ +#include "driver/uart.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "string.h" +#include "gps.h" + +#define TAG "GPS" +#define BUF_SIZE 1024 +#define GPS_LINE_MAX_LEN 128 + +static QueueHandle_t uart_queue; + +// Initializes UART for GPS +void gps_init() +{ + uart_config_t uart_config = { + .baud_rate = 9600, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, + .rx_flow_ctrl_thresh = 122, + }; + ESP_ERROR_CHECK(uart_param_config(GPS_UART_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(GPS_UART_NUM, GPS_TXD, GPS_RXD, GPS_RTS, GPS_CTS)); + + const int uart_buffer_size = (1024 * 2); + ESP_ERROR_CHECK(uart_driver_install(GPS_UART_NUM, uart_buffer_size, uart_buffer_size, 10, &uart_queue, 0)); +} + + +void gps_task(void *arg) +{ + uint8_t byte; + char line[GPS_LINE_MAX_LEN]; + size_t line_pos = 0; + + gps_init(); + + while (1) { + int len = uart_read_bytes(GPS_UART_NUM, &byte, 1, pdMS_TO_TICKS(1000)); + if (len > 0) { + if (byte == '\n') { + line[line_pos] = '\0'; + + if (line[0] == '$') { + ESP_LOGV(TAG, "Received NMEA: %s", line); + + if (strstr(line, "$GPGGA") == line) { + parse_gpgga(line); + } else if (strstr(line, "$GPRMC") == line) { + parse_gprmc(line); + } + } + + line_pos = 0; + } else if (byte != '\r' && line_pos < (GPS_LINE_MAX_LEN - 1)) { + line[line_pos++] = byte; + } else if (line_pos >= GPS_LINE_MAX_LEN - 1) { + ESP_LOGW(TAG, "Line too long, discarded"); + line_pos = 0; + } + } + } +} + +void parse_gpgga(const char *nmea) +{ + char *fields[15]; + char temp[GPS_LINE_MAX_LEN]; + strncpy(temp, nmea, GPS_LINE_MAX_LEN); + temp[GPS_LINE_MAX_LEN - 1] = '\0'; + + int i = 0; + char *token = strtok(temp, ","); + while (token != NULL && i < 15) { + fields[i++] = token; + token = strtok(NULL, ","); + } + + if (i < 10) return; // Not enough fields + + // Time (hhmmss.sss) + const char *utc_time = fields[1]; + + // Latitude (ddmm.mmmm) + const char *lat = fields[2]; + const char *lat_dir = fields[3]; + + // Longitude (dddmm.mmmm) + const char *lon = fields[4]; + const char *lon_dir = fields[5]; + + // Fix quality (0 = invalid, 1 = GPS fix, 2 = DGPS fix) + const char *fix_quality = fields[6]; + + // Number of satellites + const char *num_satellites = fields[7]; + + // Altitude + const char *altitude = fields[9]; + + ESP_LOGI(TAG, "[GPGGA] Time: %s, Lat: %s %s, Lon: %s %s, Fix: %s, Sats: %s, Alt: %sm", + utc_time, lat, lat_dir, lon, lon_dir, fix_quality, num_satellites, altitude); +} + +void parse_gprmc(const char *nmea) +{ + char *fields[13]; + char temp[GPS_LINE_MAX_LEN]; + strncpy(temp, nmea, GPS_LINE_MAX_LEN); + temp[GPS_LINE_MAX_LEN - 1] = '\0'; + + int i = 0; + char *token = strtok(temp, ","); + while (token != NULL && i < 13) { + fields[i++] = token; + token = strtok(NULL, ","); + } + + if (i < 12) return; + + const char *utc_time = fields[1]; + const char *status = fields[2]; // A = active, V = void + const char *lat = fields[3]; + const char *lat_dir = fields[4]; + const char *lon = fields[5]; + const char *lon_dir = fields[6]; + const char *speed_knots = fields[7]; + const char *date = fields[9]; + + ESP_LOGI(TAG, "[GPRMC] Date: %s, Time: %s, Lat: %s %s, Lon: %s %s, Speed: %s knots, Status: %s", + date, utc_time, lat, lat_dir, lon, lon_dir, speed_knots, status); +} + diff --git a/main/hw/gps.h b/main/hw/gps.h new file mode 100644 index 0000000..7713b78 --- /dev/null +++ b/main/hw/gps.h @@ -0,0 +1,14 @@ +#ifndef GPS_COMPONENT +#define GPS_COMPONENT + +#include "driver/uart.h" +#include "soc/uart_struct.h" +#include "buscfg.h" + + + +void gps_task(void *arg); +void parse_gpgga(const char *nmea); +void parse_gprmc(const char *nmea); + +#endif \ No newline at end of file diff --git a/main/hw/i2cbrn.c b/main/hw/i2cbrn.c index 559f08a..90bae7c 100644 --- a/main/hw/i2cbrn.c +++ b/main/hw/i2cbrn.c @@ -3,50 +3,84 @@ i2c_master_bus_config_t i2c0_bus_cfg = { .clk_source = I2C_CLK_SRC_DEFAULT, .i2c_port = I2C_NUM_0, - .scl_io_num = GPIO_NUM_9, - .sda_io_num = GPIO_NUM_8, + .scl_io_num = HWI2C_SCL, + .sda_io_num = HWI2C_SDA, .glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true, }; i2c_master_bus_handle_t i2c0_bus_hdl; -esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle) -{ - const uint16_t probe_timeout_ms = 50; // timeout in milliseconds - uint8_t address; +// esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle) +// { +// const uint16_t probe_timeout_ms = 20; // timeout in milliseconds +// uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); +// printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) - { - printf("%02x: ", i); +// for (int i = 0; i < 128; i += 16) +// { +// printf("%02x: ", i); - for (int j = 0; j < 16; j++) - { - fflush(stdout); +// for (int j = 0; j < 16; j++) +// { +// fflush(stdout); - address = i + j; +// address = i + j; - esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms); +// esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms); - if (ret == ESP_OK) - { - printf("%02x ", address); - } - else if (ret == ESP_ERR_TIMEOUT) - { - printf("UU "); - } - else - { - printf("-- "); - } - } - printf("\r\n"); - } +// if (ret == ESP_OK) +// { +// printf("%02x ", address); +// } +// else if (ret == ESP_ERR_TIMEOUT) +// { +// printf("UU "); +// } +// else +// { +// printf("-- "); +// } +// } +// printf("\r\n"); +// } - return ESP_OK; -} +// return ESP_OK; +// } + + +/** + * i2c master initialization + */ + + esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle) + { + uint8_t address; + bool found_any = false; + + printf("Scanning I2C bus...\n"); + + for (int i = 0; i < 128; i++) + { + fflush(stdout); + address = i; + + esp_err_t ret = i2c_master_probe(handle, address, 20); + + if (ret == ESP_OK) + { + printf("Found device at 0x%02X\n", address); + found_any = true; + } + } + + if (!found_any) + { + printf("No I2C devices found.\n"); + } + + return ESP_OK; + } /** * @brief Writes data to a specific register of an I2C device. diff --git a/main/hw/i2cbrn.h b/main/hw/i2cbrn.h index 347a848..60d465b 100644 --- a/main/hw/i2cbrn.h +++ b/main/hw/i2cbrn.h @@ -3,6 +3,7 @@ #define I2C_TIMEOUT_MS_VALUE 20 #include #include "esp_log.h" +#include "buscfg.h" #define TAG_I2C "cani2c" diff --git a/main/hw/ina260.c b/main/hw/ina260.c index 9e4fd82..2d1d38f 100644 --- a/main/hw/ina260.c +++ b/main/hw/ina260.c @@ -16,7 +16,8 @@ void ina260_reset() { void ina260_init() { ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE)); - i2c_write_register_16(INA260_DEV_HANDLE, INA260_CONFIG_REGISTER, 0x0FFF); // set ina max averaging and max time + i2c_write_register_16(INA260_DEV_HANDLE, INA260_CONFIG_REGISTER, + CONFIG_AVG_1024 | CONFIG_VBUSCT_8_244MS | CONFIG_ISHCT_8_244MS | CONFIG_MODE_CURRENT_VOLTAGE_CONTINOUS); // set ina max averaging and max time } diff --git a/main/hw/ina260.h b/main/hw/ina260.h index 5d931d5..83088b0 100644 --- a/main/hw/ina260.h +++ b/main/hw/ina260.h @@ -16,60 +16,57 @@ extern i2c_master_dev_handle_t INA260_DEV_HANDLE; #define INA260_DIE_ID_REGISTER (0xFF) // Bit masks -#define CONFIG_RST_BIT (1 << 15) -#define CONFIG_AVG_MASK (0x7 << 9) -#define CONFIG_VBUSCT_MASK (0x7 << 6) -#define CONFIG_ISHCT_MASK (0x7 << 3) -#define CONFIG_MODE_MASK (0x7 << 0) +#define CONFIG_RST_BIT (1 << 15) +#define CONFIG_AVG_MASK (0x7 << 9) +#define CONFIG_VBUSCT_MASK (0x7 << 6) +#define CONFIG_ISHCT_MASK (0x7 << 3) +#define CONFIG_MODE_MASK (0x7 << 0) // Read-only bits -#define CONFIG_RESERVED_BITS (0x7 << 12) // Bits 14–12 = 110b +#define CONFIG_RESERVED_BITS (0x7 << 12) // Bits 14–12 = 110b // Averaging modes (AVG) -#define CONFIG_AVG_1 (0x0 << 9) -#define CONFIG_AVG_4 (0x1 << 9) -#define CONFIG_AVG_16 (0x2 << 9) -#define CONFIG_AVG_64 (0x3 << 9) -#define CONFIG_AVG_128 (0x4 << 9) -#define CONFIG_AVG_256 (0x5 << 9) -#define CONFIG_AVG_512 (0x6 << 9) -#define CONFIG_AVG_1024 (0x7 << 9) +#define CONFIG_AVG_1 (0x0 << 9) +#define CONFIG_AVG_4 (0x1 << 9) +#define CONFIG_AVG_16 (0x2 << 9) +#define CONFIG_AVG_64 (0x3 << 9) +#define CONFIG_AVG_128 (0x4 << 9) +#define CONFIG_AVG_256 (0x5 << 9) +#define CONFIG_AVG_512 (0x6 << 9) +#define CONFIG_AVG_1024 (0x7 << 9) // Bus voltage conversion time (VBUSCT) -#define CONFIG_VBUSCT_140US (0x0 << 6) -#define CONFIG_VBUSCT_204US (0x1 << 6) -#define CONFIG_VBUSCT_332US (0x2 << 6) -#define CONFIG_VBUSCT_588US (0x3 << 6) -#define CONFIG_VBUSCT_1_1MS (0x4 << 6) -#define CONFIG_VBUSCT_2_116MS (0x5 << 6) -#define CONFIG_VBUSCT_4_156MS (0x6 << 6) -#define CONFIG_VBUSCT_8_244MS (0x7 << 6) +#define CONFIG_VBUSCT_140US (0x0 << 6) +#define CONFIG_VBUSCT_204US (0x1 << 6) +#define CONFIG_VBUSCT_332US (0x2 << 6) +#define CONFIG_VBUSCT_588US (0x3 << 6) +#define CONFIG_VBUSCT_1_1MS (0x4 << 6) +#define CONFIG_VBUSCT_2_116MS (0x5 << 6) +#define CONFIG_VBUSCT_4_156MS (0x6 << 6) +#define CONFIG_VBUSCT_8_244MS (0x7 << 6) // Shunt current conversion time (ISHCT) -#define CONFIG_ISHCT_140US (0x0 << 3) -#define CONFIG_ISHCT_204US (0x1 << 3) -#define CONFIG_ISHCT_332US (0x2 << 3) -#define CONFIG_ISHCT_588US (0x3 << 3) -#define CONFIG_ISHCT_1_1MS (0x4 << 3) -#define CONFIG_ISHCT_2_116MS (0x5 << 3) -#define CONFIG_ISHCT_4_156MS (0x6 << 3) -#define CONFIG_ISHCT_8_244MS (0x7 << 3) +#define CONFIG_ISHCT_140US (0x0 << 3) +#define CONFIG_ISHCT_204US (0x1 << 3) +#define CONFIG_ISHCT_332US (0x2 << 3) +#define CONFIG_ISHCT_588US (0x3 << 3) +#define CONFIG_ISHCT_1_1MS (0x4 << 3) +#define CONFIG_ISHCT_2_116MS (0x5 << 3) +#define CONFIG_ISHCT_4_156MS (0x6 << 3) +#define CONFIG_ISHCT_8_244MS (0x7 << 3) // Operating mode (MODE) -#define CONFIG_MODE_POWERDOWN (0x0 << 0) -#define CONFIG_MODE_CURRENT_TRIGGER (0x1 << 0) -#define CONFIG_MODE_VOLTAGE_TRIGGER (0x2 << 0) -#define CONFIG_MODE_CURRENT_VOLTAGE_TRIGGER (0x3 << 0) -#define CONFIG_MODE_POWERDOWN2 (0x4 << 0) -#define CONFIG_MODE_POWERDOWN (0x5 << 0) -#define CONFIG_MODE_POWERDOWN (0x6 << 0) -#define CONFIG_MODE_POWERDOWN (0x7 << 0) - - +#define CONFIG_MODE_POWERDOWN 0x00 +#define CONFIG_MODE_CURRENT_TRIGGER 0x01 +#define CONFIG_MODE_VOLTAGE_TRIGGER 0x02 +#define CONFIG_MODE_CURRENT_VOLTAGE_TRIGGER 0x03 +#define CONFIG_MODE_POWERDOWN2 0x04 +#define CONFIG_MODE_CURRENT_CONTINOUS 0x05 +#define CONFIG_MODE_VOLTAGE_CONTINOUS 0x06 +#define CONFIG_MODE_CURRENT_VOLTAGE_CONTINOUS 0x07 void ina260_init(); void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow); void ina260_printParams(uint16_t volt, uint16_t cur, uint16_t pow); - #endif \ No newline at end of file diff --git a/main/hw/mcp23018.c b/main/hw/mcp23018.c index cba0dd5..825ce22 100644 --- a/main/hw/mcp23018.c +++ b/main/hw/mcp23018.c @@ -1,4 +1,6 @@ #include "mcp23018.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" // Local buffer for tracking GPIO state i2c_device_config_t MCP23018_DEV_CFG = { @@ -36,6 +38,7 @@ void mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t v // Write updated buffer to MCP23018 i2c_write_register_8(dev_handle, MCP23018_GPIOB, gpiob_state); } + vTaskDelay(1 / portTICK_PERIOD_MS); } void mcp23018_init() diff --git a/main/hw/mcp3550.c b/main/hw/mcp3550.c new file mode 100644 index 0000000..7571241 --- /dev/null +++ b/main/hw/mcp3550.c @@ -0,0 +1,118 @@ +#include "mcp3550.h" +#include "mcp23018.h" +#include "driver/gpio.h" +#include + + +#define TAG_MICS "MICS_ADC" +#define MCP3550_SPS 3.75f +#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms +#define MCP3550_TIMEOUT_MS 400 + +#define ADC_COUNT 4 +const uint8_t adc_cs_pins[ADC_COUNT] = { + MCP_CS_ADC_NH3, MCP_CS_ADC_CO, MCP_CS_ADC_NO2, MCP_CS_ADC_UVC +}; + + +spi_device_handle_t mcp3550_handle; + +void mcp3550_spi_init() +{ + spi_device_interface_config_t devcfg = { + .clock_speed_hz = 100000, + .mode = 0, + .spics_io_num = -1, // We handle CS manually + .queue_size = 1, + }; + + ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &mcp3550_handle)); + + // Set MISO pin for input (needed for polling) + gpio_set_direction(MCP3550_MISO_GPIO, GPIO_MODE_INPUT); + mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_MICS_POWER, 1); // CS HIGH +} + + +int32_t mcp3550_read(uint8_t cs_pin) +{ + uint8_t rx_buf[4] = {0}; // 25 bits fits in 4 bytes + + int64_t start = esp_timer_get_time(); // in microseconds + while (true) { + mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW + + spi_transaction_t trans = { + .length = 25, + .rx_buffer = rx_buf, + }; + + esp_err_t err = spi_device_transmit(mcp3550_handle, &trans); + + mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH + + if (err != ESP_OK) { + ESP_LOGE(TAG_MICS, "SPI transmit failed on CS pin %u", cs_pin); + return INT32_MIN; + } + + bool dr = (rx_buf[0] & 0x80) != 0; + if (!dr) break; + + if ((esp_timer_get_time() - start) > (MCP3550_TIMEOUT_MS * 1000)) { + ESP_LOGW(TAG_MICS, "Timeout waiting for DR=0 on CS pin %u", cs_pin); + return INT32_MIN; + } + + vTaskDelay(pdMS_TO_TICKS(10)); // Wait before retrying + } + + // Combine 22-bit result (drop DR + status bits) + uint32_t raw = ((rx_buf[0] & 0x3F) << 16) | (rx_buf[1] << 8) | rx_buf[2]; + + // Sign-extend 22-bit value + int32_t value = raw; + if (value & (1 << 21)) value |= 0xFFC00000; + + return value; +} + + +float mcp3550_to_voltage(int32_t value, float vref) +{ + return ((float)value / (1 << 21)) * vref; +} + +mics_adc_data_t mcp3550_read_all(float vref) +{ + mics_adc_data_t data; + int32_t raw[ADC_COUNT]; + float volts[ADC_COUNT]; + + for (int i = 0; i < ADC_COUNT; i++) { + raw[i] = mcp3550_read(adc_cs_pins[i]); + vTaskDelay(pdMS_TO_TICKS(10)); // Wait before retrying + volts[i] = mcp3550_to_voltage(raw[i], vref); + } + + data.raw_nh3 = raw[0]; data.volts_nh3 = volts[0]; + data.raw_co = raw[1]; data.volts_co = volts[1]; + data.raw_no2 = raw[2]; data.volts_no2 = volts[2]; + data.raw_uvc = raw[3]; data.volts_uvc = volts[3]; + + return data; +} + +void log_mics_adc_values(mics_adc_data_t *data) +{ + ESP_LOGI(TAG_MICS, + "ADC Readings:\n" + " NH3 -> Raw: %8d, Voltage: %7.6f V\n" + " CO -> Raw: %8d, Voltage: %7.6f V\n" + " NO2 -> Raw: %8d, Voltage: %7.6f V\n" + " UVC -> Raw: %8d, Voltage: %7.6f V", + data->raw_nh3, data->volts_nh3, + data->raw_co, data->volts_co, + data->raw_no2, data->volts_no2, + data->raw_uvc, data->volts_uvc); +} diff --git a/main/hw/mcp3550.h b/main/hw/mcp3550.h new file mode 100644 index 0000000..7e8733f --- /dev/null +++ b/main/hw/mcp3550.h @@ -0,0 +1,38 @@ +#ifndef MPC3550_COMPONENT +#define MPC3550_COMPONENT + +#include "driver/spi_master.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "buscfg.h" + +#define CONFIG_FREERTOS_HZ 100 + +#define MCP3550_SPS 3.75f +#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms + + +extern spi_device_handle_t mcp3550_handle; + +void mcp3550_spi_init(); +int32_t mcp3550_read(uint8_t cs_pin); +float mcp3550_to_voltage(int32_t value, float vref); + +typedef struct { + int32_t raw_nh3; + int32_t raw_co; + int32_t raw_no2; + int32_t raw_uvc; + float volts_nh3; + float volts_co; + float volts_no2; + float volts_uvc; +} mics_adc_data_t; + +extern spi_device_handle_t mcp3550_handle; + +void log_mics_adc_values(mics_adc_data_t *data); +mics_adc_data_t mcp3550_read_all(float vref); + +#endif \ No newline at end of file diff --git a/main/hw/sx1262.c b/main/hw/sx1262.c new file mode 100644 index 0000000..22cce0a --- /dev/null +++ b/main/hw/sx1262.c @@ -0,0 +1,578 @@ +#include "sx1262.h" + +spi_device_handle_t spiSXko; + +#define TAG_SPIDUMP "[SPI]" + +void sx1262_init() +{ + ESP_LOGI(TAG, "Initializing SX1262..."); + + gpio_set_direction(HSPI_LORA_CS, GPIO_MODE_OUTPUT); + gpio_set_direction(LORA_BUSY, GPIO_MODE_INPUT); + + gpio_set_level(HSPI_LORA_CS, 1); + mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_LORA_RST, 1); + + spi_bus_config_t buscfg; + memset(&buscfg, 0, sizeof(spi_bus_config_t)); + buscfg.miso_io_num = HSPI_MISO_GPIO; + buscfg.mosi_io_num = HSPI_MOSI_GPIO; + buscfg.sclk_io_num = HSPI_SCK_GPIO; + buscfg.max_transfer_sz = 32; + buscfg.quadwp_io_num = -1; + buscfg.quadhd_io_num = -1; + + spi_device_interface_config_t devcfg = { + .command_bits = 0, + .address_bits = 0, + .mode = 0, + .cs_ena_pretrans = 10, + .clock_speed_hz = 8 * 1000 * 1000, + .spics_io_num = HSPI_LORA_CS, + .flags = 0, + .queue_size = 1}; + + ESP_LOGI(TAG, "Adding SPI device..."); + esp_err_t ret = spi_bus_add_device(LORA_SPI_HOST, &devcfg, &spiSXko); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "SPI device init failed!"); + return; + } + + ESP_LOGI(TAG, "SX1262 Initialized"); + sx1262_reset(); +} + +void sx1262_reset() +{ + ESP_LOGI(TAG, "Resetting SX1262..."); + vTaskDelay(pdMS_TO_TICKS(10)); + mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_LORA_RST, 0); + vTaskDelay(pdMS_TO_TICKS(20)); + mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_LORA_RST, 1); + vTaskDelay(pdMS_TO_TICKS(10)); + sx1262_wait_for_busy(); + ESP_LOGI(TAG, "SX1262 Reset complete."); +} + +void sx1262_wait_for_busy() +{ + ESP_LOGV("WAIT", "Waiting for SX1262 to be ready..."); + while (gpio_get_level(LORA_BUSY) == 1) + { + vTaskDelay(pdMS_TO_TICKS(10)); + } + ESP_LOGV("WAIT", "SX1262 is ready."); +} + +void sx1262_write_command(uint8_t cmd, uint8_t *data, uint8_t len) +{ + ESP_LOGV(TAG, "Writing command 0x%02X with length %d", cmd, len); + spi_transaction_t t; + memset(&t, 0, sizeof(t)); + t.length = (len + 1) * 8; + uint8_t *tx_data = malloc(len + 1); + memset(tx_data, 0, len + 1); + tx_data[0] = cmd; + if (len) + { + memcpy(tx_data + 1, data, len); + } + t.tx_buffer = tx_data; + + sx1262_wait_for_busy(); + + ESP_LOGI(TAG_SPIDUMP, "SPI TX (cmd 0x%02X):", cmd); + ESP_LOG_BUFFER_HEXDUMP(TAG_SPIDUMP, tx_data, len + 1, ESP_LOG_INFO); + + esp_err_t ret = spi_device_transmit(spiSXko, &t); + + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "SPI write failed!"); + } + else + { + ESP_LOGV(TAG, "SPI write successful"); + } + free(tx_data); +} + +uint8_t SX1262_STATUS = 0; + +void sx1262_read_command(uint8_t cmd, uint8_t *tx_payload_buffer, uint8_t tx_payload_len, uint8_t *rx_buffer, uint8_t len) +{ + ESP_LOGV(TAG, "Reading command 0x%02X with expected length %d", cmd, len); + spi_transaction_t t; + memset(&t, 0, sizeof(t)); + t.length = (len + 2) * 8; + uint8_t *tx_data = malloc(len + 2); + uint8_t *rx_data = malloc(len + 2); + memset(tx_data, 0, len + 2); + memset(rx_data, 0, len + 2); + + memset(tx_data, 0, sizeof(tx_data)); + memset(rx_data, 0, sizeof(rx_data)); + if (tx_payload_buffer != NULL && tx_payload_len > 0) + { + if (tx_payload_len > len + 1) + { + tx_payload_len = len + 1; + } + memcpy(tx_data + 1, tx_payload_buffer, tx_payload_len); + } + tx_data[0] = cmd; + + t.tx_buffer = tx_data; + t.rx_buffer = rx_data; + + sx1262_wait_for_busy(); + + ESP_LOGI(TAG_SPIDUMP, "SPI TX (cmd 0x%02X):", cmd); + ESP_LOG_BUFFER_HEXDUMP(TAG_SPIDUMP, tx_data, len + 1, ESP_LOG_INFO); + + esp_err_t ret = spi_device_transmit(spiSXko, &t); + + if (ret == ESP_OK) + { + SX1262_STATUS = rx_data[1]; + memcpy(rx_buffer, &rx_data[2], len); + ESP_LOGI(TAG_SPIDUMP, "SPI RX (cmd 0x%02X):", cmd); + ESP_LOG_BUFFER_HEXDUMP(TAG_SPIDUMP, rx_data, len + 2, ESP_LOG_INFO); + ESP_LOGV(TAG_SPIDUMP, "SPI read successful, status: 0x%02X", SX1262_STATUS); + } + else + { + ESP_LOGE(TAG, "SPI read failed!"); + } + free(rx_data); + free(tx_data); +} + +void resolve_status_byte(uint8_t status, uint16_t op_error) +{ + const char *chip_modes[] = { + "Unused", "RFU", "STBY_RC", "STBY_XOSC", + "FS", "RX", "TX", "RFU"}; + + const char *command_statuses[] = { + "Reserved", "RFU", "Data is available to host", "Command timeout", + "Command processing error", "Failure to execute command", "Command TX done", "RFU"}; + + uint8_t chip_mode = (status >> 4) & 0x07; // Bits 6:4 + uint8_t command_status = (status >> 1) & 0x07; // Bits 3:1 + + const char *chip_mode_str = chip_modes[chip_mode]; + const char *command_status_str = command_statuses[command_status]; + + const char *op_errors[] = { + "RC64k calibration failed", + "RC13M calibration failed", + "PLL calibration failed", + "ADC calibration failed", + "IMG calibration failed", + "XOSC failed to start", + "PLL failed to lock", + "RFU", + "PA ramping failed"}; + + char errorStr[1024]; + memset(errorStr, 0, sizeof(errorStr)); + + if (command_status == 0x05) + { + strcat(errorStr, "Command error: "); + } + + for (int i = 0; i < 9; i++) + { + if (op_error & (1 << i)) + { + strcat(errorStr, op_errors[i]); + strcat(errorStr, ", "); + ESP_LOGV(TAG, "OpError: %s", op_errors[i]); + } + } + + ESP_LOGI(TAG, "Chip Mode: %s(0x%02X), Command Status: %s(0x%02X) %s", chip_mode_str, chip_mode, command_status_str, command_status, errorStr); +} + +sx1262_status_t sx1262_get_status() +{ + ESP_LOGV(TAG, "Getting SX1262 status..."); + sx1262_status_t status; + uint8_t buffer[1] = {0}; + sx1262_read_command(0xC0, NULL, 0, buffer, 1); + status.status = buffer[0]; + status.error = sx1262_getDeviceErrors(); + sx1262_clearDeviceErrors(); + resolve_status_byte(status.status, status.error); + return status; +} + +void sx1262_setSleep(uint8_t sleepCFG) +{ + sx1262_write_command(0x84, &sleepCFG, 1); +} + +void sx1262_setStandby(uint8_t standbyConf) +{ + sx1262_write_command(0x80, &standbyConf, 1); +} + +void sx1262_setFrequencySynthesis() +{ + sx1262_write_command(0xC1, NULL, 0); +} + +void sx1262_setMode(uint8_t mode, uint32_t timeout) +{ + + uint32_t timeoutUnits = 0; + + if (timeout != 0) + { + uint64_t timeoutInUs = (uint64_t)timeout * 1000; // Convert ms → us + timeoutUnits = (uint32_t)((timeoutInUs * 64) / 1000); // Convert us → SX1262 units + } + + uint8_t buffer[4] = { + (uint8_t)((timeoutUnits >> 24) & 0xFF), + (uint8_t)((timeoutUnits >> 16) & 0xFF), + (uint8_t)((timeoutUnits >> 8) & 0xFF), + (uint8_t)((timeoutUnits) & 0xFF)}; + if (mode) + { + sx1262_write_command(0x83, buffer, 3); + } + else + { + sx1262_write_command(0x82, buffer, 3); + } +} + +void sx1262_stopTimerOnPreamble(uint8_t enable) +{ + sx1262_write_command(0x9F, &enable, 1); +} + +void sx1262_setRxDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod) +{ + uint8_t payload[6]; + payload[0] = (rxPeriod >> 16) & 0xFF; + payload[1] = (rxPeriod >> 8) & 0xFF; + payload[2] = rxPeriod & 0xFF; + payload[3] = (sleepPeriod >> 16) & 0xFF; + payload[4] = (sleepPeriod >> 8) & 0xFF; + payload[5] = sleepPeriod & 0xFF; + sx1262_write_command(0x94, payload, 6); +} + +void sx1262_setChannelActivityDetection(void) +{ + sx1262_write_command(0xC5, NULL, 0); +} + +void sx1262_setTxContinuousWave(void) +{ + sx1262_write_command(0xD1, NULL, 0); +} + +void sx1262_setTxInfinitePreamble(void) +{ + sx1262_write_command(0xD2, NULL, 0); +} + +void sx1262_setRegulatorMode(uint8_t mode) +{ + sx1262_write_command(0x96, &mode, 1); +} + +void sx1262_calibrate(uint8_t calibParam) +{ + sx1262_write_command(0x89, &calibParam, 1); +} + +void sx1262_calibrateImage(uint8_t freq1, uint8_t freq2) +{ + uint8_t payload[2] = {freq1, freq2}; + sx1262_write_command(0x98, payload, 2); +} + +void sx1262_setRxTXFallbackMode(uint8_t fallbackMode) +{ + sx1262_write_command(0x93, &fallbackMode, 1); +} + +// Write to register function +void sx1262_writeRegister(uint16_t address, const uint8_t *data, size_t length) +{ + uint8_t payload[length + 2]; + payload[0] = (address >> 8) & 0xFF; + payload[1] = address & 0xFF; + for (size_t i = 0; i < length; i++) + { + payload[i + 2] = data[i]; + } + sx1262_write_command(0x0D, payload, length + 2); +} + +// Read from register function +void sx1262_readRegister(uint16_t address, uint8_t *data, size_t length) +{ + uint8_t payload[2]; + payload[0] = (address >> 8) & 0xFF; + payload[1] = address & 0xFF; + uint8_t rx_payload[2 + length]; + sx1262_read_command(0x1D, payload, 2, rx_payload, 2 + length); + for (size_t i = 0; i < length; i++) + { + data[i] = rx_payload[i + 2]; + } +} + +// Write to buffer function +void sx1262_writeBuffer(uint8_t offset, const uint8_t *data, size_t length) +{ + uint8_t payload[length + 1]; + payload[0] = offset; + for (size_t i = 0; i < length; i++) + { + payload[i + 1] = data[i]; + } + sx1262_write_command(0x0E, payload, length + 1); +} + +// Read from buffer function +void sx1262_readBuffer(uint8_t offset, uint8_t *data, size_t length) +{ + uint8_t tx_payload[1]; + uint8_t payload[1 + length]; + tx_payload[0] = offset; + sx1262_read_command(0x1E, tx_payload, 1, payload, 1 + length); + for (size_t i = 0; i < length; i++) + { + data[i] = payload[i + 1]; + } +} + +void sx1262_setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) +{ + uint8_t payload[8] = { + (uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)((irqMask) & 0xFF), + (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF), + (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF), + (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)}; + sx1262_write_command(0x08, payload, 8); +} + +uint16_t sx1262_getIrqStatus(void) +{ + uint8_t response[2] = {0}; + sx1262_read_command(0x12, NULL, 0, response, 2); + return (response[0] << 8) | response[1]; +} + +void sx1262_clearIrqStatus(uint16_t clearIrqParam) +{ + uint8_t payload[2] = { + (uint8_t)((clearIrqParam >> 8) & 0xFF), + (uint8_t)(clearIrqParam & 0xFF)}; + sx1262_write_command(0x02, payload, 2); +} + +void sx1262_setDIO2AsRfSwitchCtrl(uint8_t enable) +{ + uint8_t buf[1]; + buf[0] = enable; + sx1262_write_command(0x9D, buf, 1); +} + +void sx1262_setDIO3AsTCXOCtrl(uint8_t tcxoVoltage, uint32_t delay) +{ + uint8_t payload[4] = { + tcxoVoltage, + (uint8_t)((delay >> 16) & 0xFF), + (uint8_t)((delay >> 8) & 0xFF), + (uint8_t)(delay & 0xFF)}; + sx1262_write_command(0x97, payload, 4); +} + +void sx1262_setFrequency(uint32_t frequency) +{ + uint32_t freq_reg = frequency * FREQ_STEP; + uint8_t buffer[4] = { + (uint8_t)((freq_reg >> 24) & 0xFF), + (uint8_t)((freq_reg >> 16) & 0xFF), + (uint8_t)((freq_reg >> 8) & 0xFF), + (uint8_t)((freq_reg) & 0xFF)}; + sx1262_write_command(0x86, buffer, 4); +} + +void sx1262_setPacketType(uint8_t packetType) +{ + uint8_t data[1]; + data[0] = packetType; + sx1262_write_command(0x8A, data, 1); +} + +void sx1262_setLoRaModulationParams(const sx1262_LoRaModulationParams_t *params) +{ + uint8_t payload[4] = { + params->spreadingFactor, + params->bandwidth, + params->codingRate, + params->lowDataRateOpt}; + sx1262_write_command(0x8B, payload, sizeof(payload)); +} + +void sx1262_setGFSKModulationParams(const sx1262_GFSKModulationParams_t *params) +{ + uint8_t payload[8] = { + (uint8_t)((params->bitRate >> 16) & 0xFF), + (uint8_t)((params->bitRate >> 8) & 0xFF), + (uint8_t)(params->bitRate & 0xFF), + params->pulseShape, + params->bandwidth, + (uint8_t)((params->frequencyDev >> 16) & 0xFF), + (uint8_t)((params->frequencyDev >> 8) & 0xFF), + (uint8_t)(params->frequencyDev & 0xFF)}; + sx1262_write_command(0x8B, payload, sizeof(payload)); +} + +uint8_t sx1262_getPacketType() +{ + uint8_t response; + sx1262_read_command(0x11, NULL, 0, &response, 1); + return response; +} + +void sx1262_configure_tx_power(uint8_t paDutyCycle, uint8_t hpMax, uint8_t paLut, int8_t power, uint8_t rampTime) +{ + if (paDutyCycle > 0x04) + paDutyCycle = 0x04; + if (rampTime > 0x07) + rampTime = 0x07; + if (hpMax > 0x07) + hpMax = 0x07; + + uint8_t deviceSel; + if (power >= -9) + { + deviceSel = 0x00; // High Power PA + if (power > 22) + power = 22; + if (power < -9) + power = -9; + } + else + { + deviceSel = 0x01; // Low Power PA + if (power > 14) + power = 14; + if (power < -17) + power = -17; + } + + uint8_t paConfig[4] = {paDutyCycle, hpMax, deviceSel, paLut}; + sx1262_write_command(0x95, paConfig, 4); + + // Direct cast keeps correct 2's complement representation + uint8_t txPower[2] = {(uint8_t)power, rampTime}; + sx1262_write_command(0x8E, txPower, 2); +} + +void sx1262_setLoRaPacketParams(sx1262_LoRaPacketParams_t *params) +{ + uint8_t payload[6] = { + (uint8_t)((params->preambleLength >> 8) & 0xFF), + (uint8_t)(params->preambleLength & 0xFF), + params->headerType, + params->payloadLength, + params->crcType, + params->invertIQ}; + sx1262_write_command(0x8C, payload, sizeof(payload)); +} + +void sx1262_setCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout) +{ + uint8_t payload[7] = { + cadSymbolNum, + cadDetPeak, + cadDetMin, + cadExitMode, + (uint8_t)((cadTimeout >> 16) & 0xFF), + (uint8_t)((cadTimeout >> 8) & 0xFF), + (uint8_t)(cadTimeout & 0xFF)}; + sx1262_write_command(0x88, payload, sizeof(payload)); +} + +void sx1262_setBufferBaseAddress(uint8_t txBaseAddr, uint8_t rxBaseAddr) +{ + uint8_t payload[2] = {txBaseAddr, rxBaseAddr}; + sx1262_write_command(0x8F, payload, sizeof(payload)); +} + +void sx1262_setLoRaSymbNumTimeout(uint8_t symbNum) +{ + sx1262_write_command(0xA0, &symbNum, 1); +} + +void sx1262_getStatus(uint8_t *status) +{ + sx1262_read_command(0xC0, NULL, 0, status, 0); +} + +void sx1262_getRxBufferStatus(uint8_t *payloadLengthRx, uint8_t *rxStartBufferPointer) +{ + uint8_t response[2]; + sx1262_read_command(0x13, NULL, 0, response, sizeof(response)); + *payloadLengthRx = response[0]; + *rxStartBufferPointer = response[1]; +} + +void sx1262_getPacketStatus(uint8_t *rssi, uint8_t *snr, uint8_t *signalRssi) +{ + uint8_t response[3]; + sx1262_read_command(0x14, NULL, 0, response, sizeof(response)); + *rssi = response[0]; + *snr = response[1]; + *signalRssi = response[2]; +} + +uint8_t sx1262_getRssiInst(uint8_t *rssiInst) +{ + uint8_t response; + sx1262_read_command(0x15, NULL, 0, &response, 1); + return response; +} + +void sx1262_getStats(uint16_t *pktReceived, uint16_t *pktCrcError, uint16_t *pktHeaderErr) +{ + uint8_t response[6]; + sx1262_read_command(0x10, NULL, 0, response, sizeof(response)); + *pktReceived = (response[0] << 8) | response[1]; + *pktCrcError = (response[2] << 8) | response[3]; + *pktHeaderErr = (response[4] << 8) | response[5]; +} + +void sx1262_resetStats(void) +{ + uint8_t payload[6] = {0}; + sx1262_write_command(0x00, payload, sizeof(payload)); +} + +uint16_t sx1262_getDeviceErrors() +{ + uint8_t response[2]; + sx1262_read_command(0x17, NULL, 0, response, sizeof(response)); + return (((uint16_t)response[0]) << 8) | (uint16_t)response[1]; +} + +void sx1262_clearDeviceErrors(void) +{ + uint8_t payload[2] = {0x00, 0x00}; + sx1262_write_command(0x07, payload, sizeof(payload)); +} diff --git a/main/hw/sx1262.h b/main/hw/sx1262.h new file mode 100644 index 0000000..f43ee5e --- /dev/null +++ b/main/hw/sx1262.h @@ -0,0 +1,330 @@ +#ifndef SX1262_H +#define SX1262_H + +#include "driver/spi_master.h" +#include "driver/gpio.h" +#include +#include "buscfg.h" +#include "mcp23018.h" + +#include + +#include "esp_task.h" + +#define TAG "SX1262" + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#include "esp_log.h" + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +#define LORA_SPI_HOST SPI3_HOST + +extern spi_device_handle_t spi; + +typedef struct +{ + uint8_t status; + uint16_t error; +} sx1262_status_t; + +typedef struct +{ + uint16_t preambleLength; + uint8_t headerType; + uint8_t payloadLength; + uint8_t crcType; + uint8_t invertIQ; +} sx1262_LoRaPacketParams_t; + +#define SX126X_DIOX_OUTPUT_ENABLE 0x0580 +#define SX126X_DIOX_INPUT_ENABLE 0x0583 +#define SX126X_DIOX_PULL_UP_CONTROL 0x0584 +#define SX126X_DIOX_PULL_DOWN_CONTROL 0x0585 + +#define SX126X_WHITENING_INIT_MSB 0x06B8 +#define SX126X_WHITENING_INIT_LSB 0x06B9 + +#define SX126X_CRC_INIT_MSB 0x06BC +#define SX126X_CRC_INIT_LSB 0x06BD + +#define SX126X_CRC_POLY_MSB 0x06BE +#define SX126X_CRC_POLY_LSB 0x06BF + +#define SX126X_SYNCWORD_0 0x06C0 +#define SX126X_SYNCWORD_1 0x06C1 +#define SX126X_SYNCWORD_2 0x06C2 +#define SX126X_SYNCWORD_3 0x06C3 +#define SX126X_SYNCWORD_4 0x06C4 +#define SX126X_SYNCWORD_5 0x06C5 +#define SX126X_SYNCWORD_6 0x06C6 +#define SX126X_SYNCWORD_7 0x06C7 + +#define SX126X_NODE_ADDRESS 0x06CD +#define SX126X_BROADCAST_ADDRESS 0x06CE + +#define SX126X_IQ_POLARITY_SETUP 0x0736 + +#define SX126X_LORA_SYNCWORD_MSB 0x0740 +#define SX126X_LORA_SYNCWORD_LSB 0x0741 + +#define SX126X_RANDOM_NUMBER_0 0x0819 +#define SX126X_RANDOM_NUMBER_1 0x081A +#define SX126X_RANDOM_NUMBER_2 0x081B +#define SX126X_RANDOM_NUMBER_3 0x081C + +#define SX126X_TX_MODULATION 0x0889 +#define SX126X_RX_GAIN 0x08AC + +#define SX126X_TX_CLAMP_CONFIG 0x08D8 +#define SX126X_OCP_CONFIGURATION 0x08E7 + +#define SX126X_RTC_CONTROL 0x0902 + +#define SX126X_XTA_TRIM 0x0911 +#define SX126X_XTB_TRIM 0x0912 + +#define SX126X_DIO3_OUTPUT_VOLTAGE 0x0920 +#define SX126X_EVENT_MASK 0x0944 + +// Default values where applicable +#define SX126X_RX_GAIN_POWER_SAVING 0x94 +#define SX126X_RX_GAIN_BOOSTED 0x96 + +#define SX126X_LORA_SYNCWORD_PUBLIC 0x3444 +#define SX126X_LORA_SYNCWORD_PRIVATE 0x1424 + +#define SX126X_OCP_LEVEL_SX1262 0x38 // 140mA +#define SX126X_OCP_LEVEL_SX1261 0x18 // 60mA + +typedef struct +{ + uint8_t spreadingFactor; // LoRa SF: 0x05 (SF5) to 0x0C (SF12) + uint8_t bandwidth; // LoRa BW: 0x00 (7.81 kHz) to 0x06 (500 kHz) + uint8_t codingRate; // LoRa CR: 0x01 (4/5) to 0x04 (4/8) + uint8_t lowDataRateOpt; // LDRO: 0x00 (disabled) or 0x01 (enabled) +} sx1262_LoRaModulationParams_t; + +typedef struct +{ + uint32_t bitRate; // GFSK bitrate (BR), calculated as 32 * Fxtal / BR + uint8_t pulseShape; // GFSK filter: 0x00 (none) to 0x0B (Gaussian BT 1) + uint8_t bandwidth; // GFSK RX bandwidth: 0x1F (4.8 kHz) to 0x09 (467 kHz) + uint32_t frequencyDev; // GFSK frequency deviation (Fdev) +} sx1262_GFSKModulationParams_t; + +#include + +#define XTAL_FREQ (double)32000000 +#define FREQ_DIV (double)pow(2.0, 25.0) +#define FREQ_STEP (double)(XTAL_FREQ / FREQ_DIV) + +#define SX1262_SLEEPCFG_ColdStart_RTCDisable 0 +#define SX1262_SLEEPCFG_ColdStart_RTCEnable 1 +#define SX1262_SLEEPCFG_WarmStart_RTCDisable 4 +#define SX1262_SLEEPCFG_WarmStart_RTCEnable 5 + +#define SX1262_STANDBY_RC 0 +#define SX1262_STANDBY_XOSC 1 + +#define SX1262_TIMEOUT_ONCE 0 +#define SX1262_TIMEOUT_RX_CONTINOUS 0xFFFFFF + +#define SX1262_RECEIVE_MODE 0 +#define SX1262_TRANSMIT_MODE 1 + +#define SX1262_STOP_TIMER_ON_PREAMBLE_DISABLE 0x00 +#define SX1262_STOP_TIMER_ON_PREAMBLE_ENABLE 0x01 + +#define SX1262_REGULATOR_LDO_ONLY 0x00 +#define SX1262_REGULATOR_DC_DC_LDO 0x01 + +#define SX1262_FALLBACK_FS 0x40 +#define SX1262_FALLBACK_STANDBY_XOSC 0x30 +#define SX1262_FALLBACK_RC 0x20 + +#define SX1262_IRQ_TXDone (1 << 0) +#define SX1262_IRQ_RXDone (1 << 1) +#define SX1262_IRQ_PreambleDetected (1 << 2) +#define SX1262_IRQ_SyncWordValid (1 << 3) +#define SX1262_IRQ_HeaderValid (1 << 4) +#define SX1262_IRQ_HeaderError (1 << 5) +#define SX1262_IRQ_CRCError (1 << 6) +#define SX1262_IRQ_ChannelActivityDetectionDone (1 << 7) +#define SX1262_IRQ_ChannelActivityDetected (1 << 8) +#define SX1262_IRQ_Timeout (1 << 9) +#define SX1262_IRQ_ALL (SX1262_IRQ_TXDone | SX1262_IRQ_RXDone | SX1262_IRQ_PreambleDetected | SX1262_IRQ_SyncWordValid | SX1262_IRQ_HeaderValid | SX1262_IRQ_HeaderError | SX1262_IRQ_CRCError | SX1262_IRQ_ChannelActivityDetectionDone | SX1262_IRQ_ChannelActivityDetected | SX1262_IRQ_Timeout) + +#define SX1262_TCXO_VOLTAGE16dV 0x00 +#define SX1262_TCXO_VOLTAGE17dV 0x01 +#define SX1262_TCXO_VOLTAGE18dV 0x02 +#define SX1262_TCXO_VOLTAGE22dV 0x03 +#define SX1262_TCXO_VOLTAGE24dV 0x04 +#define SX1262_TCXO_VOLTAGE27dV 0x05 +#define SX1262_TCXO_VOLTAGE30dV 0x06 +#define SX1262_TCXO_VOLTAGE33dV 0x07 + +#define SX1262_PACKET_TYPE_GFSK 0x00 +#define SX1262_PACKET_TYPE_LORA 0x01 + +#define SX1262_Ramp_10U (0x00) +#define SX1262_Ramp_20U (0x01) +#define SX1262_Ramp_40U (0x02) +#define SX1262_Ramp_80U (0x03) +#define SX1262_Ramp_200U (0x04) +#define SX1262_Ramp_800U (0x05) +#define SX1262_Ramp_1700U (0x06) +#define SX1262_Ramp_3400U (0x07) + +#define SX1262_HEADER_TYPE_VARIABLE 0x00 +#define SX1262_HEADER_TYPE_FIXED 0x01 + +#define SX1262_CRC_OFF 0x00 +#define SX1262_CRC_ON 0x01 + +#define SX1262_STANDARD_IQ 0x00 +#define SX1262_INVERTED_IQ 0x01 + +#define SX1262_CAD_ON_1_SYMB 0x00 +#define SX1262_CAD_ON_2_SYMB 0x01 +#define SX1262_CAD_ON_4_SYMB 0x02 +#define SX1262_CAD_ON_8_SYMB 0x03 +#define SX1262_CAD_ON_16_SYMB 0x04 +#define SX1262_CAD_ONLY 0x00 +#define SX1262_CAD_RX 0x01 + +#define SX1262_ERROR_CALIBRATION_RC64K (1 << 0) +#define SX1262_ERROR_CALIBRATION_RC13M (1 << 1) +#define SX1262_ERROR_CALIBRATION_PLL (1 << 2) +#define SX1262_ERROR_CALIBRATION_ADC (1 << 3) +#define SX1262_ERROR_CALIBRATION_IMG (1 << 4) +#define SX1262_ERROR_CALIBRATION_XOSC (1 << 5) +#define SX1262_ERROR_PLL_LOCK (1 << 6) +#define SX1262_ERROR_PA_RAMP (1 << 8) + +#define SX1262_CALIB_RC64K (1 << 0) // RC64k calibration enabled +#define SX1262_CALIB_RC13M (1 << 1) // RC13M calibration enabled +#define SX1262_CALIB_PLL (1 << 2) // PLL calibration enabled +#define SX1262_CALIB_ADC_PULSE (1 << 3) // ADC pulse calibration enabled +#define SX1262_CALIB_ADC_BULK_N (1 << 4) // ADC bulk N calibration enabled +#define SX1262_CALIB_ADC_BULK_P (1 << 5) // ADC bulk P calibration enabled +#define SX1262_CALIB_IMAGE (1 << 6) // Image calibration enabled +#define SX1262_CALIB_RESERVED (1 << 7) // Reserved bit (RFU) + +// Combined mask for all calibration settings +#define SX1262_CALIBRATION_ALL (SX1262_CALIB_RC64K | SX1262_CALIB_RC13M | \ + SX1262_CALIB_PLL | SX1262_CALIB_ADC_PULSE | \ + SX1262_CALIB_ADC_BULK_N | SX1262_CALIB_ADC_BULK_P | \ + SX1262_CALIB_IMAGE) + +// GFSK Pulse Shape +#define SX1262_GFSK_NO_FILTER (0x00) +#define SX1262_GFSK_BT_0_3 (0x08) +#define SX1262_GFSK_BT_0_5 (0x09) +#define SX1262_GFSK_BT_0_7 (0x0A) +#define SX1262_GFSK_BT_1_0 (0x0B) + +// GFSK Bandwidth +#define SX1262_GFSK_RX_BW_4800 (0x1F) +#define SX1262_GFSK_RX_BW_5800 (0x17) +#define SX1262_GFSK_RX_BW_7300 (0x0F) +#define SX1262_GFSK_RX_BW_9700 (0x1E) +#define SX1262_GFSK_RX_BW_11700 (0x16) +#define SX1262_GFSK_RX_BW_14600 (0x0E) +#define SX1262_GFSK_RX_BW_19500 (0x1D) +#define SX1262_GFSK_RX_BW_23400 (0x15) +#define SX1262_GFSK_RX_BW_29300 (0x0D) +#define SX1262_GFSK_RX_BW_39000 (0x1C) +#define SX1262_GFSK_RX_BW_46900 (0x14) +#define SX1262_GFSK_RX_BW_58600 (0x0C) +#define SX1262_GFSK_RX_BW_78200 (0x1B) +#define SX1262_GFSK_RX_BW_93800 (0x13) +#define SX1262_GFSK_RX_BW_117300 (0x0B) +#define SX1262_GFSK_RX_BW_156200 (0x1A) +#define SX1262_GFSK_RX_BW_187200 (0x12) +#define SX1262_GFSK_RX_BW_234300 (0x0A) +#define SX1262_GFSK_RX_BW_312000 (0x19) +#define SX1262_GFSK_RX_BW_373600 (0x11) +#define SX1262_GFSK_RX_BW_467000 (0x09) + +// LoRa Spreading Factor (SF) +#define SX1262_LORA_SF5 (0x05) +#define SX1262_LORA_SF6 (0x06) +#define SX1262_LORA_SF7 (0x07) +#define SX1262_LORA_SF8 (0x08) +#define SX1262_LORA_SF9 (0x09) +#define SX1262_LORA_SF10 (0x0A) +#define SX1262_LORA_SF11 (0x0B) +#define SX1262_LORA_SF12 (0x0C) + +// LoRa Bandwidth (BW) +#define SX1262_LORA_BW_7 (0x00) // 7.81 kHz +#define SX1262_LORA_BW_10 (0x08) // 10.42 kHz +#define SX1262_LORA_BW_15 (0x01) // 15.63 kHz +#define SX1262_LORA_BW_20 (0x09) // 20.83 kHz +#define SX1262_LORA_BW_31 (0x02) // 31.25 kHz +#define SX1262_LORA_BW_41 (0x0A) // 41.67 kHz +#define SX1262_LORA_BW_62 (0x03) // 62.50 kHz +#define SX1262_LORA_BW_125 (0x04) // 125 kHz +#define SX1262_LORA_BW_250 (0x05) // 250 kHz +#define SX1262_LORA_BW_500 (0x06) // 500 kHz + +// LoRa Coding Rate (CR) +#define SX1262_LORA_CR_4_5 (0x01) +#define SX1262_LORA_CR_4_6 (0x02) +#define SX1262_LORA_CR_4_7 (0x03) +#define SX1262_LORA_CR_4_8 (0x04) + +#define SX1262_LORA_SYNC_WORD_MSB (0x0740) +#define SX1262_LORA_SYNC_WORD_LSB (0x0741) + +void sx1262_setPacketType(uint8_t packetType); +void sx1262_init(); +void sx1262_reset(); +void sx1262_wait_for_busy(); +void sx1262_write_command(uint8_t cmd, uint8_t *data, uint8_t len); +void sx1262_read_command(uint8_t cmd, uint8_t *tx_payload_buffer, uint8_t tx_payload_len, uint8_t *rx_buffer, uint8_t len); +sx1262_status_t sx1262_get_status(); +void sx1262_setSleep(uint8_t sleepCFG); +void sx1262_setStandby(uint8_t standbyConf); +void sx1262_setFrequencySynthesis(); +void sx1262_setMode(uint8_t mode, uint32_t timeout); +void sx1262_stopTimerOnPreamble(uint8_t enable); +void sx1262_setRxDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod); +void sx1262_setChannelActivityDetection(void); +void sx1262_setTxContinuousWave(void); +void sx1262_setTxInfinitePreamble(void); +void sx1262_setRegulatorMode(uint8_t mode); +void sx1262_calibrate(uint8_t calibParam); +void sx1262_calibrateImage(uint8_t freq1, uint8_t freq2); +void sx1262_setRxTXFallbackMode(uint8_t fallbackMode); +void sx1262_writeRegister(uint16_t address, const uint8_t *data, size_t length); +void sx1262_readRegister(uint16_t address, uint8_t *data, size_t length); +void sx1262_writeBuffer(uint8_t offset, const uint8_t *data, size_t length); +void sx1262_readBuffer(uint8_t offset, uint8_t *data, size_t length); +void sx1262_setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask); +uint16_t sx1262_getIrqStatus(void); +void sx1262_clearIrqStatus(uint16_t clearIrqParam); +void sx1262_setDIO2AsRfSwitchCtrl(uint8_t enable); +void sx1262_setDIO3AsTCXOCtrl(uint8_t tcxoVoltage, uint32_t delay); +void sx1262_setFrequency(uint32_t frequency); +uint8_t sx1262_getPacketType(); +void sx1262_configure_tx_power(uint8_t paDutyCycle, uint8_t hpMax, uint8_t paLut, int8_t power, uint8_t rampTime); +void sx1262_setLoRaPacketParams(sx1262_LoRaPacketParams_t *params); +void sx1262_setCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout); +void sx1262_setBufferBaseAddress(uint8_t txBaseAddr, uint8_t rxBaseAddr); +void sx1262_setLoRaSymbNumTimeout(uint8_t symbNum); +void sx1262_getStatus(uint8_t *status); +void sx1262_getRxBufferStatus(uint8_t *payloadLengthRx, uint8_t *rxStartBufferPointer); +void sx1262_getPacketStatus(uint8_t *rssi, uint8_t *snr, uint8_t *signalRssi); +uint8_t sx1262_getRssiInst(uint8_t *rssiInst); +void sx1262_getStats(uint16_t *pktReceived, uint16_t *pktCrcError, uint16_t *pktHeaderErr); +void sx1262_resetStats(void); +uint16_t sx1262_getDeviceErrors(); +void sx1262_clearDeviceErrors(void); + +void sx1262_setLoRaModulationParams(const sx1262_LoRaModulationParams_t *params); + +void sx1262_setGFSKModulationParams(const sx1262_GFSKModulationParams_t *params); + +#endif diff --git a/main/main.c b/main/main.c index f5c7e59..f348047 100644 --- a/main/main.c +++ b/main/main.c @@ -15,6 +15,7 @@ #include "esp_mac.h" #include +#include "components/radio.h" #include "components/sensors.h" #include "components/util.h" #include "hw/bme680b.h" @@ -23,31 +24,70 @@ #include "hw/ina260.h" #include "hw/mcp23018.h" #include "hw/mpu9250.h" +#include "hw/buscfg.h" + +#include "hw/gps.h" #define TAG "cantest" - #define CONFIG_FREERTOS_HZ 100 - void app_main(void) { /* instantiate i2c master bus 0 */ ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl)); + spi_bus_config_t MCPBusCfg = { + .mosi_io_num = -1, + .miso_io_num = MCP3550_MISO_GPIO, + .sclk_io_num = MCP3550_SCK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 4, + }; + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &MCPBusCfg, SPI_DMA_DISABLED)); + + spi_bus_config_t HighSpeedBusCfg = { + // CONNECTED to LoRa and SD card + .mosi_io_num = HSPI_MOSI_GPIO, + .miso_io_num = HSPI_MISO_GPIO, + .sclk_io_num = HSPI_SCK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 64, // probably change + }; + ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &HighSpeedBusCfg, SPI_DMA_CH_AUTO)); + /* scan i2c devices on i2c master bus 0 and print results */ ESP_ERROR_CHECK(i2c_master_bus_detect_devices(i2c0_bus_hdl)); + mcp23018_init(); + /* create task pinned to the app core */ - xTaskCreatePinnedToCore( + xTaskCreate( i2c_sensors_task, "I2CTaskBME", 8192, NULL, (tskIDLE_PRIORITY + 2), + NULL); + + xTaskCreate( + lora_comms_task, + "LoraCommsTask", + 8192, NULL, - APP_CPU_NUM); + (tskIDLE_PRIORITY + 2), + NULL); + + xTaskCreate( + gps_task, + "gps_task", + 8192, + NULL, + (tskIDLE_PRIORITY + 2), + NULL); while (1) {