/*
 * nrf24l01.h
 *
 *  Created on: 1 авг. 2019 г.
 *      Author: dima
 */

#ifndef NRF24L01_H_
#define NRF24L01_H_

//#include "main.h"
#include "string.h"
#include "stdio.h"
#include "stdbool.h"
#include "../spi/ad0x0_spi.h"
#include "../mpu6050/mpu6050.h"
#include "../gps/gps.h"

#define rf24_max(a,b) (a>b?a:b)
#define rf24_min(a,b) (a<b?a:b)

/* Memory Map */
#define NRF_CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define NRF_STATUS  0x07
#define OBSERVE_TX  0x08
#define CD          0x09
//ad0x0
#define NRF_RPD     0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD	    0x1C
#define FEATURE	    0x1D

/* Bit Mnemonics */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0
#define AW          0
#define ARD         4
#define ARC         0
#define PLL_LOCK    4
#define RF_DR       3
#define RF_PWR      6
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1
#define TX_FULL     0
#define PLOS_CNT    4
#define ARC_CNT     0
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0
#define DPL_P5	    5
#define DPL_P4	    4
#define DPL_P3	    3
#define DPL_P2	    2
#define DPL_P1	    1
#define DPL_P0	    0
#define EN_DPL	    2
#define EN_ACK_PAY  1
#define EN_DYN_ACK  0

/* Instruction Mnemonics */
#define R_REGISTER    0x00
#define W_REGISTER    0x20
#define REGISTER_MASK 0x1F
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define W_ACK_PAYLOAD 0xA8
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define NOP           0xFF

/* Non-P omissions */
#define LNA_HCURR   0

/* P model memory Map */
#define RPD         0x09
#define W_TX_PAYLOAD_NO_ACK  0xB0

/* P model bit Mnemonics */
#define RF_DR_LOW   5
#define RF_DR_HIGH  3
#define RF_PWR_LOW  1
#define RF_PWR_HIGH 2

///////////////////////////////////////////////////////////////////////////////

typedef enum
{
	RF24_PA_MIN = 0,
	RF24_PA_LOW,
	RF24_PA_HIGH,
	RF24_PA_MAX,
	RF24_PA_ERROR
} rf24_pa_dbm_e;

typedef enum
{
	RF24_1MBPS = 0,
	RF24_2MBPS,
	RF24_250KBPS
} rf24_datarate_e;

typedef enum
{
	RF24_CRC_DISABLED = 0,
	RF24_CRC_8,
	RF24_CRC_16
} rf24_crclength_e;

/*устройств rf24 планируется >1 и тут западло:
я блин херею как меня бесит этот сраный си
я долго думал как не делать тупые названия ф-й типа write_register_SPI2 
и придумал засунуть указатели ф-й SPI в регистры О_о*/

/*typedef struct{
void    (*ad0x0_spi_push)(ADQS_t _ctype,uint8_t _cbyte);
uint8_t    (*ad0x0_spi_get_ext_async2)(uint8_t *_p_out_handle,void **_p_out_spi_ext_t);
void    (*ad0x0_spi_push_ext_setfunc)(uint8_t _sf_id,void (*_p_cb_func)(uint8_t _sf_id,ad0x0_spi_desc_s *pdspi,void *p_spi_ext_t));
void    (*ad0x0_spi_push_txrx_dma_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
void    (*ad0x0_spi_push_tx_pbuf_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
void    (*ad0x0_spi_push_tx_pbuf_dma_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
}rf24_spi_desc_t, *p_rf24_spi_desc_t;*/
struct rf24_spi_regs_t;
//typedef 
__packed struct rf24_spi_REG_s{
	__packed struct rf24_spi_regs_s *pspi;//ссылка на весь сраный массив с регистрами
		uint8_t 
	radr,//адрес регистра RF24 SPI
	so,//sizeof
	//wr,//0x0 для чтения 0x20 для записи
	value;
};
typedef __packed struct rf24_spi_REG_s rf24_spi_REG_t,*p_rf24_spi_REG_t;
typedef __packed struct{
	__packed struct rf24_spi_regs_s *pspi;//уже слышу про память, сравнения с x86 и пр.херню
	uint8_t 
	radr,//адрес регистра RF24 SPI
	so,//sizeof
	value[5];//0x00
}rf24_spi_REG5_t,*p_rf24_spi_REG5_t;
//я знаю, что то что ниже - момент спорный. Не надо тока орать сразу про растрату памяти и тупость.
__packed struct rf24_spi_regs_s{
	rf24_spi_REG_t
	_CONFIG,
	_EN_AA,
	_EN_RXADDR,
	_SETUP_AW,
	_SETUP_RETR,
	_RF_CH,
	_RF_SETUP,
	_STATUS,//0x7
	_OBSERVE_TX,
	_RPD;//0x09
rf24_spi_REG5_t
	_RX_ADDR_P0,//0xA
	_RX_ADDR_P1;
rf24_spi_REG_t
	_RX_ADDR_P2,
	_RX_ADDR_P3,//0xD
	_RX_ADDR_P4,
	_RX_ADDR_P5;
rf24_spi_REG5_t
	_TX_ADDR;//0x10
rf24_spi_REG_t
	_RX_PW_P0,
	_RX_PW_P1,
	_RX_PW_P2,//0x13
	_RX_PW_P3,
	_RX_PW_P4,
	_RX_PW_P5,
	_FIFO_STATUS,//0x17
	_DYNPD,	//0x1C
	_FEATURE,//0x1D
	_R_RX_PL_WID,//cmd
	_NOP;
	GPIO_TypeDef *CE_GPIO_Port;
	uint16_t CE_Pin;
	void    (*ad0x0_spi_push)(ADQS_t _ctype,uint8_t _cbyte);
	uint8_t    (*ad0x0_spi_get_ext_async2)(uint8_t *_p_out_handle,void **_p_out_spi_ext_t);
	void    (*ad0x0_spi_push_ext_setfunc)(uint8_t _sf_id,void (*_p_cb_func)(uint8_t _sf_id,ad0x0_spi_desc_s *pdspi,void *p_spi_ext_t));
	void    (*ad0x0_spi_push_txrx_dma_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
	void    (*ad0x0_spi_push_tx_pbuf_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
	void    (*ad0x0_spi_push_tx_pbuf_dma_ext)(uint8_t *_tx_pbuf,uint8_t *_rx_pbuf, uint8_t _count);
	void 		(*powerUp)(void);
	void 		(*powerDown)(void);
	void 		(*spi_cmd)(uint8_t _cmd);
	void		(*set_ce)(uint8_t _isHigh);
	void 		(*enableRXPipe)(uint8_t _pipe_index,uint8_t _payload_size,bool _enable_AutoAck,bool _enable_DYN_PL);
	void		(*setRateAndPA)(rf24_datarate_e speed,rf24_pa_dbm_e _power);
	void		(*setRetransmission)(uint8_t delay, uint8_t count);
	void		(*PRX_readPayload_transmitAck)(uint8_t _pipe_index,uint8_t _payload_size, uint8_t _ack_payload_size);
	void 		(*PTX_transmit_pipe)(uint8_t _pipe_index);
	void 		(*PTX_read_Ack)(uint8_t _pipe_index,uint8_t _ack_payload_size);
	__packed struct packet_data_s* (*get_pipe_packet_buf)(uint8_t _pipe_index);
	__packed struct packet_ack_data_s* (*get_pipe_ack_buf)(uint8_t _pipe_index);
	__packed struct pipe_data_s* (*get_pipe_buf)(uint8_t _pipe_index);
	void 		(*PTX_start)(uint8_t _pipe_index);
	void 		(*PRX_start)(uint8_t _pipe_index,uint8_t _ack_payload_size);
	void 		(*PTX_init)(void);
	void 		(*PRX_init)(void);
	void 		(*init_pipes)(void);
	uint8_t    (*get_rssi)(void);
};//rf24_spi_regs_t;//init_nrf24_spi_regs() 1st
typedef __packed struct rf24_spi_regs_s rf24_spi_regs_t;


//void init_nrf24_spi_regs(nrf24_spi_regs_t *p);

typedef __packed struct{
	uint8_t 
	_CONFIG,//0x00
	_EN_AA,
	_EN_RXADDR,
	_SETUP_AW,
	_SETUP_RETR,//0x4 
	_RF_CH,
	_RF_SETUP,
	_STATUS,//0x7
	_OBSERVE_TX,
	_RPD,//0x09
	_RX_ADDR_P0[5],//0xA
	_RX_ADDR_P1[5],
	_RX_ADDR_P2,
	_RX_ADDR_P3,//0xD
	_RX_ADDR_P4,
	_RX_ADDR_P5,
	_TX_ADDR[5],//0x10
	_RX_PW_P0,
	_RX_PW_P1,
	_RX_PW_P2,//0x13
	_RX_PW_P3,
	_RX_PW_P4,
	_RX_PW_P5,
	_FIFO_STATUS,//0x17
	_DYNPD, //0x1C
	_FEATURE,//0x1D
	_R_RX_PL_WID,//cmd
	_NOP;
}rf24_regs_t;

/*__packed struct packet_data_s{
	uint32_t id;
	uint8_t bytes[28];
};*/

__packed struct packet_data_s{
	uint32_t id;//4
	ad0x0_gyrodata_s gyro;//14
	gps_data_t gps;//14
	uint8_t bytes[1];
};

typedef __packed struct packet_data_s packet_data_t;

__packed struct packet_ack_data_s{
	uint32_t id;
	uint8_t bytes[8];
};
typedef __packed struct packet_ack_data_s packet_data_ack_t;

__packed struct pipe_data_s{
	uint8_t bytes_count_packet;//PRX - размер Payload от PTX. Для PTX - то что отправляем в PRX
	uint8_t spi_cmd;//R_RX_PAYLOAD 0110 0001,W_TX_PAYLOAD 1010 0000
	packet_data_t packet;
	uint8_t bytes_count_ack;//PRX - размер AckPayload, для PTX - то что пришло от PRX
	uint8_t spi_cmd_ack;//
	packet_data_ack_t packet_ack;
};
typedef __packed struct pipe_data_s pipe_data_t;

uint8_t NRF_Init(void);
void 	rf24_init_spi1_regs(rf24_spi_regs_t *p,GPIO_TypeDef *CE_GPIO_Port, uint16_t CE_Pin);
void 	rf24_init_spi2_regs(rf24_spi_regs_t *p,GPIO_TypeDef *CE_GPIO_Port, uint16_t CE_Pin);
void	rf24_spi1_scan_channels(uint8_t _sf_id,void (*_p_cb_func)(uint8_t _sf_id,ad0x0_spi_desc_s *pdspi,void *p_spi_ext_t));
void	rf24_spi2_scan_channels(uint8_t _sf_id,void (*_p_cb_func)(uint8_t _sf_id,ad0x0_spi_desc_s *pdspi,void *p_spi_ext_t));
void	read_all_regs(rf24_spi_regs_t *p_spi_regs,rf24_regs_t *pregs);
void	read_all_regs_postprocess(rf24_spi_regs_t *p_spi_regs,rf24_regs_t *pregs);
void 	ad0x0_rf24_spi1_irq(void);
void 	ad0x0_rf24_spi2_irq(void);
void 	rf24_tx_pipe(uint8_t _pipe_index);
void	read_register(rf24_spi_REG_t *preg_radr);
void	read_register5(rf24_spi_REG5_t *preg_radr);
void	write_register(rf24_spi_REG_t *preg_radr, uint8_t _val);
void  write_register5(rf24_spi_REG5_t *preg_radr5, uint8_t *_buf5);
void	write_register_bits(rf24_spi_REG_t *preg_radr, uint8_t _or_bits, uint8_t _and_mask);

packet_data_t *get_pipe_packet_buf(uint8_t _pipe_index);
packet_data_ack_t *get_pipe_ack_buf(uint8_t _pipe_index);





#endif /* NRF24L01_H_ */
