/*
  ============================================================================
  FOXHUNT — ОБЩИЙ ЗАГОЛОВОК (единый источник правды для всех ролей)
  ============================================================================
  Сюда вынесено ВСЁ, что обязано СОВПАДАТЬ у Лисы, Охотника и Фальшлисы:
  радио-параметры, структура пакета, таблица ВЧ-ключа E77, учебная подпись.

  ПОЧЕМУ ОТДЕЛЬНЫЙ ФАЙЛ: раньше эти вещи были скопированы в каждый .ino.
  Стоило поправить одно поле в структуре в одном файле и забыть в другом —
  и роли переставали понимать друг друга. Теперь правка в одном месте.

  КАК ПОДКЛЮЧИТЬ: положите этот файл рядом с .ino (в той же папке скетча)
  и напишите вверху скетча:  #include "foxhunt_common.h"

  ЖЕЛЕЗО: CDEBYTE E77-900MBL-01 (STM32WLE5CCU6). ВЧ-ключ PA6=TXEN, PA7=RXEN.
  ============================================================================
*/
#ifndef FOXHUNT_COMMON_H
#define FOXHUNT_COMMON_H

#include <RadioLib.h>

// ============================================================================
// РАДИО-ПАРАМЕТРЫ — ДОЛЖНЫ БЫТЬ ОДИНАКОВЫ У ВСЕХ РОЛЕЙ
// ============================================================================
// Частота: 868.7–869.2 МГц в РФ исторически разрешает 25 мВт со свободной
// скважностью (проверьте АКТУАЛЬНУЮ редакцию решения ГКРЧ — нормы меняются).
// Для пеленгации важна свободная скважность: лиса вещает часто.
#define LORA_FREQ_MHZ       869.0f
#define LORA_BW_KHZ         125.0f

// SF7 (а не SF10!) — ОСОЗНАННЫЙ выбор для пеленгации:
//   airtime пакета ~30 мс вместо ~330 мс → можно слать маяк часто,
//   а частый маяк = плавная стрелка "громкости" при движении/вращении.
//   Потеря чувствительности ~7-8 дБ против SF10 роли не играет: в здании и
//   парке дистанции малы. Для дальней уличной охоты см. коммент в лисе.
#define LORA_SF             7
#define LORA_CR             5        // 4/5
#define LORA_SYNC_WORD      0x12     // приватная сеть (не 0x34 = LoRaWAN public)
#define LORA_PREAMBLE       8

// Мощность. 14 дБм = 25 мВт. НЕ превышать разрешённое! Для ближней охоты
// в здании можно СНИЗИТЬ (см. FOX_TX_PWR_DBM в лисе) — так RSSI не насыщается.
#define LORA_TX_PWR_DBM     14

// ============================================================================
// СТРУКТУРА ПАКЕТА-МАЯКА (компактный бинарный формат, 9 байт)
//   Offset Size Field
//   0      1    fox_id      — какая лиса (1..5, как MOE/MOI/... в ARDF)
//   1      4    fcnt        — счётчик кадров (для урока про replay-защиту)
//   5      2    bat_mv      — напряжение питания, мВ (телеметрия)
//   7      1    tx_pwr_dbm  — мощность TX, дБм (signed! для расчёта FSPL)
//   8      1    signature   — учебная 1-байтовая подпись (см. ниже)
// ============================================================================
#pragma pack(push, 1)
struct FoxBeacon_t {
  uint8_t  fox_id;
  uint32_t fcnt;
  uint16_t bat_mv;
  int8_t   tx_pwr_dbm;
  uint8_t  signature;
};
#pragma pack(pop)

// ============================================================================
// УЧЕБНАЯ ПОДПИСЬ
//   ЧЕСТНОЕ ПРЕДУПРЕЖДЕНИЕ ДЛЯ УРОКА: эта подпись СЛАБАЯ НАМЕРЕННО.
//   XOR всех ключевых байтов схлопывается в одну константу, поэтому подпись
//   фактически = XOR(данные) ^ K, где K — одна константа. Её можно подобрать
//   перебором 256 значений НЕ ЗНАЯ ключа. Это НЕ баг — это учебный материал:
//   на этом показываем, ЗАЧЕМ настоящие системы берут AES-CMAC (см. LoRaWAN-
//   ветку проекта). Не использовать нигде, кроме класса.
// ============================================================================
#define HMAC_KEY_LEN  8
static const uint8_t HMAC_KEY[HMAC_KEY_LEN] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0x13, 0x37
};

// Подпись по всем полям, КРОМЕ самого байта signature (последний).
static inline uint8_t foxCalcSignature(const FoxBeacon_t &pkt) {
  const uint8_t *raw = (const uint8_t*)&pkt;
  uint8_t sig = 0;
  for (uint8_t i = 0; i < sizeof(FoxBeacon_t) - 1; i++) {
    sig ^= raw[i] ^ HMAC_KEY[i % HMAC_KEY_LEN];
  }
  return sig;
}

// ============================================================================
// ТАБЛИЦА ВЧ-КЛЮЧА E77 — ГРАБЛИ ЖЕЛЕЗА, задокументированы и обойдены
//   E77-900M22S разведён ТОЛЬКО на RFO_HP. MODE_TX_LP убран НАМЕРЕННО:
//   иначе при power<=15 дБм RadioLib ушёл бы на неподключённый RFO_LP и
//   в эфир пошла бы только утечка (RSSI у приёмника падает на ~80 дБ).
//   _rfPins ОБЯЗАН содержать ровно RFSWITCH_MAX_PINS (5) элементов — иначе
//   ссылка const uint32_t(&)[5] в setRfSwitchTable не биндится (ошибка сборки).
//
//   ИСПОЛЬЗОВАНИЕ (в begin() каждой роли, ДО radio.begin()):
//     radio.setRfSwitchTable(FOX_RF_PINS, FOX_RF_TABLE);
//   Массивы объявлены static, чтобы жили в каждой единице трансляции.
// ============================================================================
static const uint32_t FOX_RF_PINS[Module::RFSWITCH_MAX_PINS] =
    { PA6, PA7, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };

static const Module::RfSwitchMode_t FOX_RF_TABLE[] = {
  { STM32WLx::MODE_IDLE,  {LOW,  LOW } },  // оба LOW: ключ закрыт, ток не течёт
  { STM32WLx::MODE_RX,    {LOW,  HIGH} },
  { STM32WLx::MODE_TX_HP, {HIGH, LOW } },  // единственный TX-режим этого модуля
  END_OF_MODE_TABLE,
};

// OCP: HP PA не душить по току.
#define FOX_OCP_MA  140.0f

#endif // FOXHUNT_COMMON_H
