#ifndef RF_H
#define RF_H

// Protocole version
 #define RF_VERSION     1.02

/*
 * MANCHESTER CODING (George E. Thomas 1949)
 * ----------------------------------------
 *  Bit "1" (HL)        Bit "0" (LH)
 *    ___                    ___
 *   |   |                  |   |
 *   |   |____          ____|   |
 *
 *
 * PWM FOR MANCHESTER
 * ------------------
 * We need to go twice faster than bit rate on PWM to be able to create transition.
 * PWM pulse is a half bit.
 *
 *   CODE  |   1   |   0   |   1   |   1   |   1   |   0   |   0   |
 *          ___         _______     ___     ___         ___     ___
 *         |   |       |       |   |   |   |   |       |   |   |   |
 *     ... |   |_______|       |___|   |___|   |_______|   |___|   | ...
 *   PWM   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^   ^
 *
 *
 * PACKET FORMAT
 * -------------
 * The packet is the minimum useful data, it is encapsulated in a FRAME, and FRAMEs are encapsulated in a BURST.
 *
 *  <PID> <FLAGS> <ADDR> <CMD> [PAYLOAD] <CRC8>
 *
 *      PID         : Packet ID (modulo 255) same for all TRY, incremented after each transmission (1 byte)
 *      FLAGS       : Frame flags (1 byte)
 *                      bit 7     GRP     : ADDR field is a group
 *                      bit 6-4   TRY     : Tx try (0 to retry-1) wait "(retry - 1 - TRY) * frame_duration" before execution
 *                      bit 3-0   PSIZE   : Payload size (0 - 15 byte)
 *      ADDR        : Receiver address or Receiver group (see GRP bit) 0=Broadcast (1 byte)
 *      CMD         : Command to execute (1 byte)
 *      PAYLOAD     : payload (Optionnal), max 7 bytes (1 byte)
 *      CRC         : CRC8 computed from PID to end of PAYLOAD included (1 byte)
 *
 * Max payload size     : 7 bytes (3 bits)
 * Min packet size      : 5 bytes
 * Max packet size      : 12 bytes
 *
 *
 * FRAME FORMAT
 * ------------
 * The FRAME incorporates receiver synchronization data.
 *
 *  {GAP} <PREAMBLE> <SYNCH> <SYNCL> {...PACKET...} {PUHER}
 *
 *      GAP         : Silence (LLLLL...) during 3 ms to synchronize pulse level
 *      PREAMBLE    : 0xFF "HLHLHLHLHLHLHLHL" (1 byte)      "1 1 1 1 1 1 1 1"
 *      SYNC_WORD   : 0x2DD4 (2 byte)                       "0 0101 101 1 101010 0"
 *      PUSHER      : 1 bit "HL" "1" to properly close the last bit of CRC
 *
 *
 * BURST FORMAT
 * ------------
 * The BURST is the transmission block; it integrates the retransmission of the FRAME as well as the data necessary for the radio transmitter.
 *
 *  {WAKEUP} {WAIT} {KICKSTART} ... {FRAME} {FRAME} {FRAME} ... {LOW}
 *
 *      WAKEUP      : Pulse (H) to wakeup the hardware transmitter
 *      WAIT        : Silence (L) to wait hardware transmitter is ready
 *      KICKSTART   : Log high pulse to stabilize the receiver AGC
 *      LOW         : Silence (L) to proper finish transmission
 *
 *
 *
 */


// ============================================================================
//                                   CONSTANTES
// ============================================================================


 // Timer
 #define RF_TIM_FREQ                    1000000                                 // Timer at 1MHz

// Bit rate
#define RF_BIT_RATE                     4000                                    // Symbol rate
#define RF_BIT_US                       (RF_TIM_FREQ / RF_BIT_RATE)             // Symbol period
#define RF_HALF_BIT_RATE                (RF_BIT_RATE * 2)                       // Half-bit frequency (Manchester : 1 bit = 2 transition)
#define RF_HALF_BIT_US                  (RF_TIM_FREQ / RF_HALF_BIT_RATE)        // Half-bit duration

// Protocol
#define RF_KICKSTART_US                 5000                                    // Kickstart pulse to stabilize AGC
#define RF_KICKSTART_HALF_BIT           RF_US_TO_HALF_BIT(RF_KICKSTART_US)      // Number of half-bit for KICKSTART
#define RF_GAP_US                       3000                                    // Silence before frame transmission (needed to know line status H or L)
#define RF_GAP_HALF_BIT                 RF_US_TO_HALF_BIT(RF_GAP_US)            // Number of half-bit for GAP
#define RF_PREAMBLE                     0xFF                                    // 0xFF (HLHLHLHL)
#define RF_SYNC_WORD                    0x2DD4                                  // Word to be sure receiver is synchronized "0010 1101 1101 0100"
#define RF_RETRY                        3                                       // Frame count in burst

// Keepalive
#define RF_KEEPALIVE_MS                 (1000 * 60)                             // TX keepalive
#define RF_KEEPALIVE_TIMEOUT_MS         (1000 * 60 * 15)                        // RX keepalive timeout (shutdown)


// Timing
#define RF_GAP_PULSE_TOLERANCE          30                                      // GAP pulse duration tolerance in percent (Jitter/Noise)
#define RF_GAP_PULSE_MIN_US             (RF_GAP_US - (RF_GAP_US * RF_GAP_PULSE_TOLERANCE / 100))
#define RF_GAP_PULSE_MAX_US             (RF_GAP_US + (RF_GAP_US * RF_GAP_PULSE_TOLERANCE / 100))
#define RF_BIT_PULSE_NOISE_MAX_US       (RF_BIT_US *  1 / 5)                    // Ignore pulse lower than, it's noise
#define RF_BIT_PULSE_LONG_MAX_US        (RF_BIT_US * 16 / 10)                   // Pulse longer than reset the decoder, it's jamming
#define RF_BIT_PULSE_SHORT_MAX_US       (RF_BIT_US *  3 / 4)                    // Limit for distinguishing a short or long pulse (3/4 of bit)

// TX Driver
#define RF_TX_DRV_WAKEUP_US             100                                     // We need a pulse at least 10ns to wakeup CMT2110LC trasmitter (page 16)
#define RF_TX_DRV_WAKEUP_HALF_BIT       RF_US_TO_HALF_BIT(RF_TX_DRV_WAKEUP_US)  // Number of half-bit period for wakeup
#define RF_TX_DRV_WAIT_US               1000                                    // We need a pulse at least 400 + 370 us to CMT2110LC trasmitter start XTAL and tune frequency (page 16)
#define RF_TX_DRV_WAIT_HALF_BIT         RF_US_TO_HALF_BIT(RF_TX_DRV_WAIT_US)    // Number of half-bit period for wait
#define RF_TX_DRV_STOP_BY_MS            20                                      // Stop condition of TX cycle (Data pin holding low for 20 ms) on CMT2110LC trasmitte

// Helper
#define RF_HALF_BIT_HIGH                RF_HALF_BIT_US                              // Half-bit HIGH period duration (us)
#define RF_HALF_BIT_LOW                 0                                           // Half-bit LOW period duration (us)
#define RF_PAYLOAD_MAX_BYTE             15                                          // Max payload size (4 bit = 2^4 - 1)
#define RF_PACKET_MIN_BYTE              5                                           // Min packet size without payload
#define RF_PACKET_MAX_BYTE              (RF_PACKET_MIN_BYTE  + RF_PAYLOAD_MAX_BYTE) // Max packet size with max payload
#define RF_PACKET_MIN_HALF_BIT          ((RF_PACKET_MIN_BYTE * 8)  * 2)             // Single packet max half-bit count
#define RF_PACKET_MAX_HALF_BIT          ((RF_PACKET_MAX_BYTE * 8)  * 2)             // Single packet max half-bit count
#define RF_FRAME_MIN_HALF_BIT           (RF_GAP_HALF_BIT + (((RF_PACKET_MIN_BYTE + 3) * 8)  * 2) + 1) // Single frame min half-bit count
#define RF_FRAME_MAX_HALF_BIT           (RF_GAP_HALF_BIT + (((RF_PACKET_MAX_BYTE + 3) * 8)  * 2) + 1) // Single frame max half-bit count
#define RF_BURST_MAX_HALF_BIT           (RF_TX_DRV_WAKEUP_HALF_BIT + RF_TX_DRV_WAIT_HALF_BIT + RF_KICKSTART_HALF_BIT +  (RF_FRAME_MAX_HALF_BIT * RF_RETRY) + 1) // Burst half-bit count
#define RF_FRAME_MIN_DURATION_US        (RF_FRAME_MIN_HALF_BIT * RF_HALF_BIT_US)
#define RF_BYTE_DURATION_US             ((8 * 2) * RF_HALF_BIT_US)

// Sanitize
#if RF_GAP_PULSE_MIN_US <= RF_BIT_PULSE_LONG_MAX_US
    #error "GAP duration must be longer than a HALF BIT long pulse !"
#endif

// ============================================================================
//                                  PACKET
// ============================================================================

// Packet field id
#define RF_PACKET_FID_PID        0
#define RF_PACKET_FID_FLAGS      1
#define RF_PACKET_FID_ADDR       2
#define RF_PACKET_FID_CMD        3
#define RF_PACKET_FID_PAYLOAD    4

// Flags
#define RF_FLAG_GRP_POS         7
#define RF_FLAG_GRP_MASK        (0x01 << RF_FLAG_GRP_POS)
#define RF_FLAG_TRY_POS         4
#define RF_FLAG_TRY_MASK        (0x07 << RF_FLAG_TRY_POS)
#define RF_FLAG_PSIZE_POS       0
#define RF_FLAG_PSIZE_MASK      (0x0F << RF_FLAG_PSIZE_POS)

// Get Flag
#define RF_FLAGS_GET_GRP(_flags)     (((_flags) & RF_FLAG_GRP_MASK)   >> RF_FLAG_GRP_POS)
#define RF_FLAGS_GET_TRY(_flags)     (((_flags) & RF_FLAG_TRY_MASK)   >> RF_FLAG_TRY_POS)
#define RF_FLAGS_GET_PSIZE(_flags)   (((_flags) & RF_FLAG_PSIZE_MASK) >> RF_FLAG_PSIZE_POS)

// Build Flag
#define RF_FLAGS_BUILD(_grp, _try, _psize) ( \
    (((_grp)   << RF_FLAG_GRP_POS)   & RF_FLAG_GRP_MASK)   | \
    (((_try)   << RF_FLAG_TRY_POS)   & RF_FLAG_TRY_MASK)   | \
    (((_psize) << RF_FLAG_PSIZE_POS) & RF_FLAG_PSIZE_MASK)   \
)


// ============================================================================
//                                  COMMANDS
// ============================================================================

// Heartbeat
#define RF_CMD_ID_NOP               0x00
// Flags
#define RF_CMD_ID_SET_ACK           0x01
#define RF_CMD_ID_SET_AUTOSAVE      0x02
// Config
#define RF_CMD_ID_SET_LED_COUNT     0x03
#define RF_CMD_ID_SET_BRIGHT        0x04
#define RF_CMD_ID_SET_BOOT          0x05
#define RF_CMD_ID_SET_FLASH         0x06
#define RF_CMD_ID_SET_GLOW          0x07
// Group
#define RF_CMD_ID_GRP_JOIN          0x08
#define RF_CMD_ID_GRP_LEAVE         0x09
#define RF_CMD_ID_GRP_CLR           0x0A
// Sequence
#define RF_CMD_ID_SEQ_SET           0x0B
#define RF_CMD_ID_SEQ_CLR           0x0C
// RF Test
#define RF_CMD_ID_RF_TEST           0x0D
// Operation
#define RF_CMD_ID_SAVE              0x0E
#define RF_CMD_ID_REBOOT            0x0F
#define RF_CMD_ID_SHUTDOWN          0x10
#define RF_CMD_ID_RESET             0x11
// True color (24bits)
#define RF_CMD_ID_TRUE_COLOR        0x70
// Led command
#define RF_CMD_ID_LED_OFF           0x80
#define RF_CMD_ID_LED_MASK          0xF8
#define RF_CMD_ID_LED_ON            0x88
#define RF_CMD_ID_LED_FLASH         0x90
#define RF_CMD_ID_LED_FLASHC        0x98
#define RF_CMD_ID_LED_GLOW          0xA0
#define RF_CMD_ID_LED_GLOWC         0xA8
// Sequence execution
#define RF_CMD_ID_SEQ_EXE_MASK      0xC0
#define RF_CMD_ID_SEQ_EXE           0xC0


// ============================================================================
//                                  COLORS
// ============================================================================

// LED colors
#define RF_COLOR_NONE           0x00
#define RF_COLOR_BLUE           0x01
#define RF_COLOR_GREEN          0x02
#define RF_COLOR_CYAN           0x03
#define RF_COLOR_RED            0x04
#define RF_COLOR_MAGENTA        0x05
#define RF_COLOR_YELLOW         0x06
#define RF_COLOR_WHITE          0x07
// Spec
#define RF_COLOR_RAND           0x08
#define RF_COLOR_XRAND          0x09
#define RF_COLOR_PREV           0x0A
// Invalid
#define RF_COLOR_INVALID        0x0F

// ============================================================================
//                                  SEQUENCE
// ============================================================================

#define RF_SEQ_TYPE_NONE        0x00
#define RF_SEQ_TYPE_FLASH       0x01
#define RF_SEQ_TYPE_GLOW        0x02

// ============================================================================
//                                   MACROS
// ============================================================================

// Get half-bit count for us duration
#define RF_US_TO_HALF_BIT(x)        (((x) + (RF_HALF_BIT_US) - 1) / (RF_HALF_BIT_US))

// Is sync
#define RF_CMD_IS_SYNC(_cmd)         (((_cmd) & 0x80) != 0)

// Command LED
#define RF_CMD_LED(_cmd, _color)     ((_cmd) | ((_color) & ~RF_CMD_ID_LED_MASK))
#define RF_CMD_LED_GET_COLOR(_cmd)   ((_cmd) & ~RF_CMD_ID_LED_MASK)

// Command SEQ
#define RF_CMD_SEQ_EXE(_seq)        (RF_CMD_ID_SEQ_EXE | ((_seq) & ~RF_CMD_ID_SEQ_EXE_MASK))
#define RF_CMD_SEQ_GET_ID(_cmd)     ((_cmd) & ~RF_CMD_ID_SEQ_EXE_MASK)

// ============================================================================
//                                   TYPE
// ============================================================================


#endif
