//
// Created by bruno on 25.2.2025.
//

#ifndef UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H
#define UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H

#include <stdint.h>
#include <stdbool.h>
#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"
#include <string.h>
#include "../audio.h"
#include <stdio.h>
#include "../ui/helper.h"
#include "../ui/main.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 (21)

#define SEQParameterEEPROM 0x1C00

typedef struct {
    uint32_t dest; //4bytes
    uint32_t src; //4bytes
    uint8_t seq; //1bytes
    uint8_t ttl; //1bytes
    uint8_t flags; //1bytes
    uint8_t data[DataPacketDataSize];
} DataPacket;

void prepareDataPacket();

void MSG_FSKSendData(DataPacket *dataPacketIn);

void MSG_EnableRX(bool enable);

void processReceivedPacket(DataPacket *packet);

uint16_t calculateCRC(uint8_t *data, size_t length);

extern DataPacket dataPacket;

extern DataPacket inBoundPacket;

typedef enum {
    SMS_NOT_ENTERING = 0,
    SMS_ENTERING_DEST,
    SMS_ENTERING_MESSAGE
} SMSEnteringState;

typedef enum {
    SMS_RESPONSE_IDLE,
    SMS_RESPONSE_ACK,
    SMS_RESPONSE_ACK_LIGHT,
    SMS_RESPONSE_RETRANSMIT,
    SMS_RESPONSE_RESEND
} SMSResponseState;

extern SMSEnteringState gEnteringSMS;
extern SMSResponseState gSMSResponseState;

extern uint8_t *dataPTR;

extern bool gGotACK;

extern uint8_t SMSResponseCounter;

void FSK_HANDLE_IRQ(unsigned short irq);

void FSKModem_TimeSlice500ms(void);

#endif //UV_K5_FIRMWARE_CUSTOM_FSKMODEM_H
