diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..53624c9 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/fskmodem.c b/app/fskmodem.c new file mode 100644 index 0000000..6f8924f --- /dev/null +++ b/app/fskmodem.c @@ -0,0 +1,219 @@ +// +// Created by bruno on 25.2.2025. +// + +#include "fskmodem.h" + +uint16_t TONE2_FREQ; + +uint8_t seq = 0; +DataPacket dataPacket; + +DataPacket inBoundPacket; + +uint8_t *dataPTR = dataPacket.data; + +SMSEnteringState gEnteringSMS = SMS_NOT_ENTERING; + +void MSG_ConfigureFSK(bool rx) { + BK4819_WriteRegister(BK4819_REG_70, TONE2_ENABLE_BIT | (96U << 0)); + + switch (gEeprom.FSKMode) { + case MOD_AFSK_2400: + TONE2_FREQ = 24779U; // Estimated + break; + case MOD_AFSK_1200: + TONE2_FREQ = 12389U; + break; + case MOD_FSK_700: + TONE2_FREQ = 7227U; + break; + case MOD_FSK_450: + TONE2_FREQ = 4646U; + break; + case MOD_FSK_1200_2400: + TONE2_FREQ = 12389U; // Default to 1200Hz, dynamic switching may be required + break; + case MOD_NOAA_SAME: + TONE2_FREQ = 2083U; // NOAA SAME uses 2083.3 Hz for mark and 1562.5 Hz for space + break; + } + + + BK4819_WriteRegister(BK4819_REG_72, TONE2_FREQ); + +// uint16_t fskConfig = FSK_ENABLE_BIT | FSK_RX_BW_1_2K | FSK_RX_GAIN_DEFAULT | FSK_PREAMBLE_TYPE_AA; +// if (gEeprom.FSKMode == MOD_AFSK_1200) { +// fskConfig = FSK_ENABLE_BIT | FSK_TX_MODE_FSK_1_2K_2_4K | FSK_RX_MODE_FSK_1_2K_2_4K_NOAA; +// } + + uint16_t fskConfig = FSK_ENABLE_BIT | FSK_PREAMBLE_TYPE_AA; + + switch (gEeprom.FSKMode) { + case MOD_FSK_700: + case MOD_FSK_450: + case MOD_FSK_1200_2400: + fskConfig |= FSK_TX_MODE_FSK_1_2K_2_4K | FSK_RX_MODE_FSK_1_2K_2_4K_NOAA | FSK_RX_BW_1_2K; + break; + case MOD_AFSK_1200: + fskConfig |= FSK_TX_MODE_FFSK_1200_1800 | FSK_RX_MODE_FFSK_1200_1800 | FSK_RX_BW_FFSK_1200_1800; + break; + case MOD_AFSK_2400: + fskConfig |= FSK_TX_MODE_FFSK_1200_2400 | FSK_RX_MODE_FFSK_1200_2400 | FSK_RX_BW_2_4K_FFSK_1200_2400; + break; + case MOD_NOAA_SAME: + fskConfig |= FSK_TX_MODE_NOAA_SAME | FSK_RX_MODE_FSK_1_2K_2_4K_NOAA | FSK_RX_BW_NOAA_SAME; + break; + default: + // Unsupported mode; keep previous setting + break; + } + + + BK4819_WriteRegister(BK4819_REG_58, fskConfig); + + BK4819_WriteRegister(BK4819_REG_5A, FSK_SYNC_BYTE0 << 8 | FSK_SYNC_BYTE1); + BK4819_WriteRegister(BK4819_REG_5B, FSK_SYNC_BYTE2 << 8 | FSK_SYNC_BYTE3); + BK4819_WriteRegister(BK4819_REG_5C, FSK_CRC_ON); + + if (rx) { + BK4819_WriteRegister(BK4819_REG_5E, (64U << 3) | (1U << 0)); + } + + size_t size = sizeof(dataPacket); + if (rx) { + size = (((size + 1) / 2) * 2) + 2; + } + BK4819_WriteRegister(BK4819_REG_5D, (size << 8)); + + BK4819_FskClearFifo(); + + uint16_t fskParams = FSK_SYNC_LEN_BIT | ((rx ? 0U : 15U) << 4); + if (gCurrentVfo->SCRAMBLING_TYPE > 0) { + fskParams |= FSK_SCRAMBLE_ENABLE; + } + BK4819_WriteRegister(BK4819_REG_59, fskParams); + + BK4819_WriteRegister(BK4819_REG_02, 0); +} + + +void MSG_EnableRX(const bool enable) { + + if (enable) { + MSG_ConfigureFSK(true); + + //if(gEeprom.MESSENGER_CONFIG.data.receive) + BK4819_FskEnableRx(); + } else { + BK4819_WriteRegister(BK4819_REG_70, 0); + BK4819_WriteRegister(BK4819_REG_58, 0); + } +} + +void MSG_FSKSendData() { + + // turn off CTCSS/CDCSS during FFSK + const uint16_t css_val = BK4819_ReadRegister(BK4819_REG_51); + BK4819_WriteRegister(BK4819_REG_51, 0); + + // set the FM deviation level + const uint16_t dev_val = BK4819_ReadRegister(BK4819_REG_40); + + { + uint16_t deviation; + switch (gEeprom.VfoInfo[gEeprom.TX_VFO].CHANNEL_BANDWIDTH) { + case BK4819_FILTER_BW_WIDE: + deviation = 1300; + break; // 20k // measurements by kamilsss655 + case BK4819_FILTER_BW_NARROW: + deviation = 1200; + break; // 10k + // case BK4819_FILTER_BW_NARROWAVIATION: deviation = 850; break; // 5k + // case BK4819_FILTER_BW_NARROWER: deviation = 850; break; // 5k + // case BK4819_FILTER_BW_NARROWEST: deviation = 850; break; // 5k + default: + deviation = 850; + break; // 5k + } + + //BK4819_WriteRegister(0x40, (3u << 12) | (deviation & 0xfff)); + BK4819_WriteRegister(BK4819_REG_40, (dev_val & 0xf000) | (deviation & 0xfff)); + } + + // REG_2B 0 + // + // <15> 1 Enable CTCSS/CDCSS DC cancellation after FM Demodulation 1 = enable 0 = disable + // <14> 1 Enable AF DC cancellation after FM Demodulation 1 = enable 0 = disable + // <10> 0 AF RX HPF 300Hz filter 0 = enable 1 = disable + // <9> 0 AF RX LPF 3kHz filter 0 = enable 1 = disable + // <8> 0 AF RX de-emphasis filter 0 = enable 1 = disable + // <2> 0 AF TX HPF 300Hz filter 0 = enable 1 = disable + // <1> 0 AF TX LPF filter 0 = enable 1 = disable + // <0> 0 AF TX pre-emphasis filter 0 = enable 1 = disable + // + // disable the 300Hz HPF and FM pre-emphasis filter + // + const uint16_t filt_val = BK4819_ReadRegister(BK4819_REG_2B); + BK4819_WriteRegister(BK4819_REG_2B, (1u << 2) | (1u << 0)); + + MSG_ConfigureFSK(false); + + + SYSTEM_DelayMs(100); + + { // load the entire packet data into the TX FIFO buffer + uint16_t *ptr = (uint16_t *) &dataPacket; + size_t wordCount = sizeof(dataPacket) / sizeof(uint16_t); + + for (size_t i = 0; i < wordCount; i++) { + BK4819_WriteRegister(BK4819_REG_5F, ptr[i]); + } + } + + // enable FSK TX + BK4819_FskEnableTx(); + + { + // allow up to 310ms for the TX to complete + // if it takes any longer then somethings gone wrong, we shut the TX down + unsigned int timeout = 1000 / 5; + + while (timeout-- > 0) { + SYSTEM_DelayMs(5); + if (BK4819_ReadRegister(BK4819_REG_0C) & (1u << 0)) { // we have interrupt flags + BK4819_WriteRegister(BK4819_REG_02, 0); + if (BK4819_ReadRegister(BK4819_REG_02) & BK4819_REG_02_FSK_TX_FINISHED) + timeout = 0; // TX is complete + } + } + } + //BK4819_WriteRegister(BK4819_REG_02, 0); + + SYSTEM_DelayMs(100); + + // disable TX + MSG_ConfigureFSK(true); + + // restore FM deviation level + BK4819_WriteRegister(BK4819_REG_40, dev_val); + + // restore TX/RX filtering + BK4819_WriteRegister(BK4819_REG_2B, filt_val); + + // restore the CTCSS/CDCSS setting + BK4819_WriteRegister(BK4819_REG_51, css_val); + + SYSTEM_DelayMs(50); + APP_EndTransmission(); + FUNCTION_Select(FUNCTION_FOREGROUND); + gUpdateStatus = true; + gUpdateDisplay = true; + gFlagEndTransmission = false; + +} + +void prepareDataPacket() { + dataPacket.src = gEeprom.FSKSRCAddress; + dataPacket.seq = seq++; +} \ No newline at end of file diff --git a/app/fskmodem.h b/app/fskmodem.h new file mode 100644 index 0000000..1ba844e --- /dev/null +++ b/app/fskmodem.h @@ -0,0 +1,106 @@ +// +// Created by bruno on 25.2.2025. +// + +#ifndef UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H +#define UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H + +#include +#include +#include "../driver/bk4819.h" +#include "../driver/bk4819-regs.h" +#include "../settings.h" +#include "stddef.h" +#include "../driver/system.h" +#include "../misc.h" +#include "../app/app.h" + +// REG_70 bit definitions +#define TONE1_ENABLE_BIT (1U << 15) +#define TONE1_GAIN_MASK (0x7FU << 8) +#define TONE2_ENABLE_BIT (1U << 7) +#define TONE2_GAIN_MASK (0x7FU << 0) + +// REG_58 bit definitions +// FSK Tx Mode Selection (REG_58<15:13>) +#define FSK_TX_MODE_FSK_1_2K_2_4K (0U << 13) // 000 +#define FSK_TX_MODE_FFSK_1200_1800 (1U << 13) // 001 +#define FSK_TX_MODE_FFSK_1200_2400 (3U << 13) // 011 +#define FSK_TX_MODE_NOAA_SAME (5U << 13) // 101 + +// FSK Rx Mode Selection (REG_58<12:10>) +#define FSK_RX_MODE_FSK_1_2K_2_4K_NOAA (0U << 10) // 000 +#define FSK_RX_MODE_FFSK_1200_1800 (7U << 10) // 111 +#define FSK_RX_MODE_FFSK_1200_2400 (4U << 10) // 100 + +// FSK Rx Gain (REG_58<9:8>) +#define FSK_RX_GAIN_DEFAULT (0U << 8) // 00 +#define FSK_RX_GAIN_TYPE_C (1U << 8) // 01 +#define FSK_RX_GAIN_TYPE_B (2U << 8) // 10 +#define FSK_UNKNOWN_MASK (3U << 6) +// FSK Preamble Type Selection (REG_58<5:4>) +#define FSK_PREAMBLE_TYPE_AA (3U << 4) // 11 +#define FSK_PREAMBLE_TYPE_55 (2U << 4) // 10 +#define FSK_PREAMBLE_TYPE_UNKNOWN (0U << 4) // 00 +// FSK Rx Bandwidth Setting (REG_58<3:1>) +#define FSK_RX_BW_2_4K_FFSK_1200_2400 (4U << 1) // 100 +#define FSK_RX_BW_1_2K (0U << 1) // 000 +#define FSK_RX_BW_FFSK_1200_1800 (1U << 1) // 001 +#define FSK_RX_BW_NOAA_SAME (2U << 1) // 010 +#define FSK_ENABLE_BIT (1U << 0) + +// REG_59 bit definitions +#define FSK_CLEAR_TX_FIFO (1U << 15) +#define FSK_CLEAR_RX_FIFO (1U << 14) +#define FSK_SCRAMBLE_ENABLE (1U << 13) +#define FSK_RX_ENABLE (1U << 12) +#define FSK_TX_ENABLE (1U << 11) +#define FSK_INVERT_RX (1U << 10) +#define FSK_INVERT_TX (1U << 9) +#define FSK_PREAMBLE_LEN_MASK (15U << 4) +#define FSK_SYNC_LEN_BIT (1U << 3) + +//#define FSK_SYNC_BYTE0 0x30 +//#define FSK_SYNC_BYTE1 0x72 +//#define FSK_SYNC_BYTE2 0x57 +//#define FSK_SYNC_BYTE3 0x6c + +#define FSK_SYNC_BYTE0 0x42 +#define FSK_SYNC_BYTE1 0x52 +#define FSK_SYNC_BYTE2 0x4E +#define FSK_SYNC_BYTE3 0x51 + +#define FSK_CRC_ON (1U << 6) +#define FSK_CRC_OFF (0U << 6) + +#define DataPacketDataSize (36) + +typedef struct { + uint32_t dest; + uint32_t src; + uint8_t seq; + uint8_t flags; + uint8_t data[DataPacketDataSize]; +} DataPacket; + +void prepareDataPacket(); + +void MSG_FSKSendData(); + +void MSG_EnableRX(bool enable); + +extern DataPacket dataPacket; + +extern DataPacket inBoundPacket; + +typedef enum { + SMS_NOT_ENTERING, + SMS_ENTERING_DEST, + SMS_ENTERING_MESSAGE +} SMSEnteringState; + +extern SMSEnteringState gEnteringSMS; + +extern uint8_t *dataPTR; + +#endif //UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H