/* UA1ZBE Custom Firmware - POCSAG Decoder
 *
 * Decodes POCSAG paging signals from FM discriminator output.
 * Supports 512 and 1200 baud rates with dynamic switching.
 *
 * POCSAG Protocol:
 * - Preamble: 0xAAAAAAAB (at least 576 bits of alternating 1010... ending with 1)
 * - Sync word: 0x7CD21538
 * - Data words: 32-bit (21 data + 10 BCH + 1 parity)
 * - BCH(31,21) code, corrects up to 2 errors per word
 *
 * Architecture:
 * - Samples audio from BK4819 discriminator (REG_69 AF output or FSK FIFO)
 * - Zero-crossing detection for bit slicing
 * - State machine: IDLE -> PREAMBLE -> SYNC -> DATA
 * - Ring buffer for decoded messages
 * - Zero malloc — all static allocation
 */

#ifndef APP_POCSAG_POCSAG_H
#define APP_POCSAG_POCSAG_H

#include <stdbool.h>
#include <stdint.h>

/* POCSAG baud rates */
#define POCSAG_BAUD_512   512
#define POCSAG_BAUD_1200  1200

/* Maximum message length in bytes (arbitrary, fits in static buffer) */
#define POCSAG_MSG_MAX_LEN  64

/* Maximum messages in ring buffer */
#define POCSAG_MSG_POOL_SIZE 8

/* Decoded message structure */
typedef struct {
    uint32_t address;       /* Address (21-bit frame address) */
    uint8_t  func;          /* Function code (2 bits) */
    char     text[POCSAG_MSG_MAX_LEN];  /* Decoded text (alpha pager) */
    uint8_t  text_len;      /* Length of decoded text */
    bool     is_alpha;      /* true = alpha pager, false = numeric */
    uint32_t timestamp;     /* System tick when received */
} pocsag_msg_t;

/* Decoder state machine states */
typedef enum {
    POCSAG_STATE_IDLE = 0,
    POCSAG_STATE_PREAMBLE,
    POCSAG_STATE_SYNC,
    POCSAG_STATE_DATA
} pocsag_state_t;

/* Decoder context — all static, no malloc */
typedef struct {
    /* Configuration */
    uint32_t baud_rate;          /* Current baud rate: 512 or 1200 */

    /* State machine */
    pocsag_state_t state;

    /* Bit accumulation */
    uint32_t  shift_reg;         /* Shift register for incoming bits */
    uint8_t   bit_count;         /* Number of bits collected in shift_reg */
    uint8_t   preamble_count;    /* Consecutive alternating bits in preamble */

    /* Sync detection */
    uint8_t   sync_word_count;   /* Number of sync words found in a row */

    /* Word collection */
    uint8_t   batch_count;       /* Words in current batch (0-16) */
    uint8_t   word_in_batch;     /* Current word position in batch */

    /* Message assembly */
    uint32_t  current_address;
    uint8_t   current_func;
    uint8_t   msg_data[POCSAG_MSG_MAX_LEN];
    uint8_t   msg_len;
    bool     msg_is_alpha;

    /* Ring buffer of decoded messages */
    pocsag_msg_t messages[POCSAG_MSG_POOL_SIZE];
    volatile uint8_t msg_read_idx;
    volatile uint8_t msg_write_idx;
    volatile uint8_t msg_count;

    /* Statistics */
    uint32_t total_bits;
    uint32_t total_words;
    uint32_t corrected_errors;
    uint32_t uncorrectable_errors;

    /* Flag for new message available */
    volatile bool msg_available;

    /* Signal active flag */
    bool signal_detected;

} pocsag_decoder_t;

/* Global decoder instance */
extern pocsag_decoder_t gPocsag;

/* === API === */

/* Initialize decoder, set baud rate */
void POCSAG_Init(uint32_t baud_rate);

/* Switch baud rate dynamically (512 <-> 1200) */
void POCSAG_SwitchBaud(uint32_t baud_rate);

/* Get current baud rate */
uint32_t POCSAG_GetBaud(void);

/* Feed audio sample (12-bit ADC value from discriminator)
 * Call this from the 10ms timeslice or a dedicated sampling timer.
 * Returns true if a bit was detected. */
bool POCSAG_FeedSample(uint16_t audio_sample);

/* Feed a single bit (after external bit-slicing) */
void POCSAG_FeedBit(bool bit);

/* Check if a decoded message is available (non-blocking) */
bool POCSAG_MessageAvailable(void);

/* Pop the next decoded message from the ring buffer */
bool POCSAG_GetMessage(pocsag_msg_t *msg);

/* Get decoder state (for display) */
pocsag_state_t POCSAG_GetState(void);

/* Get signal detection status */
bool POCSAG_SignalDetected(void);

/* Reset decoder to idle state */
void POCSAG_Reset(void);

/* Process decoder state machine (call from main loop) */
void POCSAG_Process(void);

/* Configure BK4819 for POCSAG reception on given frequency */
void POCSAG_ConfigureRadio(uint32_t frequency_hz);

/* Stop POCSAG reception, restore normal RX */
void POCSAG_Stop(void);

/* Get state description string */
const char *POCSAG_StateString(pocsag_state_t state);

#endif /* APP_POCSAG_POCSAG_H */
