/* === includes ============================================================ */
#include <avr/pgmspace.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#include <stdbool.h>
#include <util/crc16.h>
#include <avr/interrupt.h>
#include "transceiver.h"
#include "ioutil.h"
#include "timer.h"
#ifndef SNIFFER_H
#define SNIFFER_H

/* === macros ============================================================== */

#define SCAN_PERIOD_MS  (20000)
#define NL "\n\r"
#define CHANNEL_OFFSET(x)  (x > TRX_MAX_CHANNEL ? TRX_MIN_CHANNEL : (x - TRX_MIN_CHANNEL))
#define CHANNEL_MAX_OFFSET (TRX_NB_CHANNELS-1)
#define VERSION "0.1"

#define CHANNEL_NEXT_CIRCULAR(x) \
    do \
    { \
        (x)++; \
        if ((x) > TRX_MAX_CHANNEL) \
        { \
            (x) = TRX_MIN_CHANNEL; \
        } \
    } \
    while(0)

/* === types =============================================================== */
typedef enum
{
    IDLE,
    EDSCAN,
    SCAN,
    SCAN_DONE,
    SNIFF
} SHORTENUM sniffer_state_t;

typedef struct scan_result_tag
{
    uint16_t framecnt;
    uint16_t crc_ok;
    uint16_t edsum;
    uint16_t lqisum;
    uint16_t ftypes[8];
} scan_result_t;

typedef struct sniffer_context_tag
{
    sniffer_state_t state;
    channel_t cchan;
    uint8_t cpage;
    uint32_t cmask;
    
    bool chkcrc;
    
    timer_hdl_t     thdl;
    time_t          scanper;
    scan_result_t   scanres[TRX_NB_CHANNELS];
    uint8_t         scanres_reset;
    uint16_t frames;
    uint16_t irq_ur;
    uint16_t missed_frames;
} sniffer_context_t;

typedef struct
{
    uint8_t irql;
    uint8_t tmrl;
    uint8_t err;
} dbg_t;


typedef struct sniffer_packet_tag
{

    time_stamp_t ts;
    uint8_t flen;
    uint8_t *rxdata;
    uint8_t lqi;
    uint8_t ed;
    bool    crc;
} sniffer_packet_t;

/* === externals =========================================================== */
extern sniffer_context_t ctx;

/* === inline functions ==================================================== */

static inline void scan_update_frame(uint8_t flen, bool crc_ok, uint8_t lqi, uint8_t ed, uint8_t *rxbuf)
{
scan_result_t *scres;

     scres = &ctx.scanres[(ctx.cchan - TRX_MIN_CHANNEL)];
     scres->framecnt ++;
     scres->edsum +=ed;
     scres->lqisum += lqi;

     if (flen < 0x80)
     {
         /* process valid frame length */
         if (crc_ok == true)
         {
             scres->crc_ok++;
             scres->ftypes[rxbuf[0]&7] ++;
         }
         /* parse beacon */
     }
}



/* === prototypes ========================================================== */
#ifdef __cplusplus
extern "C" {
#endif

void sniffer_start(sniffer_state_t state);
void sniffer_stop(void);
void ctrl_process_input(void);

void scan_init(void);
void scan_continue(void);
#ifdef __cplusplus
} /* extern "C" */
#endif

#endif  /* #ifndef SNIFFER_H */
