12.0.0 Release

This commit is contained in:
UA3REO
2025-03-10 15:10:17 +03:00
parent 7705ae9d83
commit dedae3ffdb
7 changed files with 262 additions and 2 deletions

View File

@@ -0,0 +1,8 @@
Интерфейс предназначен для создания пользовательских устройств,
имеющих высокую степень интеграции с трансивером "Волк" Интерфейс подключается к общей I2C шине трансивера.В данном примере используется плата ESP32,
подсоединенная к 21 ноге(сигнал SDA) и 22(сигнал SCK)
Со стороны трансивера требуется включение опции Menu->TRX Settings->Wolf Interface I2C
В данный момент поддерживается : 1. Синхронизация основных параметров трансивера(частота, мода, TX / RX) 2. Выполнение и получение ответа по любой поддерживаемой CAT комманде
3. Вывод сообщения на экран трансивера

View File

@@ -0,0 +1,38 @@
/*
Wolf Interface Example Project
This sketch demonstrates basic functionality for develop user-space devices, which communicates with TRX Wolf
https://github.com/XGudron/UA3REO-DDC-Transceiver
*/
#include "Wolf.h"
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200); // enable serial port for debugging
WOLF_init(); // init TRX Wolf communication
}
// the loop function runs over and over again forever
void loop() {
Serial.println("TRX Info:");
Serial.println("Current VFO: " + String(TRX_WOLF.CurrentVFO == TRX_SELECTED_VFO_A ? "A" : "B"));
Serial.println("VFO A Frequency: " + String(TRX_WOLF.VFO_A_Frequency));
Serial.println("VFO A Mode: " + WOLF_modeToString(TRX_WOLF.VFO_A_Mode));
Serial.println("VFO A Mode is CW? " + String(TRX_WOLF.VFO_A_Mode == TRX_MODE_CW ? "Yes" : "No"));
Serial.println("VFO B Frequency: " + String(TRX_WOLF.VFO_B_Frequency));
Serial.println("VFO B Mode: " + WOLF_modeToString(TRX_WOLF.VFO_B_Mode));
Serial.println("In TX? " + String(TRX_WOLF.TX ? "Yes" : "No"));
Serial.println("In Tune? " + String(TRX_WOLF.Tune ? "Yes" : "No"));
String CAT_Answer = WOLF_catCommand("SM2"); // run CAT command and get answer
Serial.println("CAT Answer (S-Meter dBm RX1): " + CAT_Answer);
WOLF_setMessage("Hello World! " + String(millis())); // set message over FFT, may be disabled if not set
Serial.println("---");
delay(1000);
}

View File

@@ -0,0 +1,51 @@
#ifndef WOLF_h
#define WOLF_h
typedef enum {
TRX_MODE_LSB,
TRX_MODE_USB,
TRX_MODE_CW,
TRX_MODE_NFM,
TRX_MODE_WFM,
TRX_MODE_AM,
TRX_MODE_SAM_STEREO,
TRX_MODE_SAM_LSB,
TRX_MODE_SAM_USB,
TRX_MODE_DIGI_L,
TRX_MODE_DIGI_U,
TRX_MODE_IQ,
TRX_MODE_LOOPBACK,
TRX_MODE_RTTY,
TRX_MODE_DSB,
} TRX_MODE;
typedef enum {
TRX_SELECTED_VFO_A,
TRX_SELECTED_VFO_B,
} TRX_SELECTED_VFO;
typedef struct { // TRX information structure
uint8_t CurrentVFO;
uint64_t VFO_A_Frequency;
uint64_t VFO_B_Frequency;
uint8_t VFO_A_Mode;
uint8_t VFO_B_Mode;
char CAT_Answer[64];
bool TX;
bool Tune;
} tWOLF;
typedef struct { // Interface information structure
bool hasDataChanges;
char Message[64];
char CAT_Command[64];
} tWOLFInterface;
extern tWOLF TRX_WOLF;
extern void WOLF_init(void);
extern String WOLF_modeToString(uint8_t mode);
extern void WOLF_setMessage(String message);
extern String WOLF_catCommand(String command);
#endif

View File

@@ -0,0 +1,129 @@
#include "Wolf.h"
#include "driver/i2c.h"
#include "freertos/FreeRTOS.h"
#define WOLF_I2C_SLAVE_SDA_IO GPIO_NUM_21
#define WOLF_I2C_SLAVE_SCL_IO GPIO_NUM_22
#define WOLF_I2C_SLAVE_NUM I2C_NUM_0
#define WOLF_I2C_ADDR 0b1110110 // without RW bit
#define WOLF_BUF_LEN 256
tWOLF TRX_WOLF;
tWOLFInterface TRX_INTERFACE;
static uint8_t WOLF_inBuff[WOLF_BUF_LEN];
static uint8_t WOLF_outBuff[WOLF_BUF_LEN];
static esp_err_t WOLF_i2c_slave_init() {
i2c_config_t conf_slave;
conf_slave.sda_io_num = WOLF_I2C_SLAVE_SDA_IO;
conf_slave.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf_slave.scl_io_num = WOLF_I2C_SLAVE_SCL_IO;
conf_slave.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf_slave.mode = I2C_MODE_SLAVE;
conf_slave.slave.addr_10bit_en = 0;
conf_slave.slave.slave_addr = WOLF_I2C_ADDR;
conf_slave.slave.maximum_speed = 300000;
conf_slave.clk_flags = 0;
i2c_param_config(WOLF_I2C_SLAVE_NUM, &conf_slave);
return i2c_driver_install(WOLF_I2C_SLAVE_NUM, conf_slave.mode, WOLF_BUF_LEN, WOLF_BUF_LEN, 0);
}
static void WOLF_i2c_background_task(void *arg) {
while (1) {
size_t size = i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, WOLF_inBuff, 1, 1000 / portTICK_RATE_MS);
if (size != 1) {
continue;
}
if (WOLF_inBuff[0] == 0x10) // write structure command
{
size = i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, WOLF_inBuff, 1, 1000 / portTICK_RATE_MS);
if (size != 1) {
continue;
}
if (WOLF_inBuff[0] == 0x01) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.CurrentVFO, sizeof(TRX_WOLF.CurrentVFO), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x02) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.VFO_A_Frequency, sizeof(TRX_WOLF.VFO_A_Frequency), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x03) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.VFO_B_Frequency, sizeof(TRX_WOLF.VFO_B_Frequency), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x04) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.VFO_A_Mode, sizeof(TRX_WOLF.VFO_A_Mode), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x05) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.VFO_B_Mode, sizeof(TRX_WOLF.VFO_B_Mode), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x06) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.CAT_Answer, sizeof(TRX_WOLF.CAT_Answer), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x07) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.TX, sizeof(TRX_WOLF.TX), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x08) {
i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)&TRX_WOLF.Tune, sizeof(TRX_WOLF.Tune), 1000 / portTICK_RATE_MS);
}
}
if (WOLF_inBuff[0] == 0x20) // read has changes? command
{
WOLF_outBuff[0] = TRX_INTERFACE.hasDataChanges ? 0x01 : 0x00;
i2c_reset_tx_fifo(WOLF_I2C_SLAVE_NUM);
i2c_slave_write_buffer(WOLF_I2C_SLAVE_NUM, WOLF_outBuff, 1, 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x30) // read data from interface command
{
size = i2c_slave_read_buffer(WOLF_I2C_SLAVE_NUM, WOLF_inBuff, 1, 1000 / portTICK_RATE_MS);
if (size != 1) {
continue;
}
i2c_reset_tx_fifo(WOLF_I2C_SLAVE_NUM);
if (WOLF_inBuff[0] == 0x01) {
i2c_slave_write_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)TRX_INTERFACE.Message, sizeof(TRX_INTERFACE.Message), 1000 / portTICK_RATE_MS);
}
if (WOLF_inBuff[0] == 0x02) {
i2c_slave_write_buffer(WOLF_I2C_SLAVE_NUM, (uint8_t *)TRX_INTERFACE.CAT_Command, sizeof(TRX_INTERFACE.CAT_Command), 1000 / portTICK_RATE_MS);
memset(TRX_INTERFACE.CAT_Command, 0x00, sizeof(TRX_INTERFACE.CAT_Command));
}
TRX_INTERFACE.hasDataChanges = false;
}
}
}
void WOLF_init(void) {
ESP_ERROR_CHECK(WOLF_i2c_slave_init());
xTaskCreate(WOLF_i2c_background_task, "wolf-task", 1024 * 2, (void *)1, 10, NULL);
}
String WOLF_modeToString(uint8_t mode) {
const char *MODE_DESCR[] = {"LSB", "USB", "CW", "NFM", "WFM", "AM", "SAM", "AM-L", "AM-U", "DIGL", "DIGU", "IQ", "LOOP", "RTTY", "DSB"};
return String(MODE_DESCR[mode]);
}
void WOLF_setMessage(String message) {
message.toCharArray(TRX_INTERFACE.Message, sizeof(TRX_INTERFACE.Message));
TRX_INTERFACE.hasDataChanges = true;
}
String WOLF_catCommand(String command) {
memset(TRX_WOLF.CAT_Answer, 0x00, sizeof(TRX_WOLF.CAT_Answer));
command.toCharArray(TRX_INTERFACE.CAT_Command, sizeof(TRX_INTERFACE.CAT_Command));
TRX_INTERFACE.hasDataChanges = true;
uint32_t startMs = esp_timer_get_time() / 1000;
while ((esp_timer_get_time() / 1000) - startMs < 2000) { // CAT Timeout
if (strlen(TRX_WOLF.CAT_Answer) > 0) {
return String(TRX_WOLF.CAT_Answer);
}
}
return "";
}